Merge pull request #105 from collin80/WIP
Merge Wip Changes into Master
This commit is contained in:
+4
-2
@@ -64,7 +64,8 @@ SOURCES += main.cpp\
|
|||||||
bus_protocols/isotp_handler.cpp \
|
bus_protocols/isotp_handler.cpp \
|
||||||
bus_protocols/j1939_handler.cpp \
|
bus_protocols/j1939_handler.cpp \
|
||||||
bus_protocols/uds_handler.cpp \
|
bus_protocols/uds_handler.cpp \
|
||||||
jsedit.cpp
|
jsedit.cpp \
|
||||||
|
frameplaybackobject.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
can_structs.h \
|
can_structs.h \
|
||||||
@@ -117,7 +118,8 @@ HEADERS += mainwindow.h \
|
|||||||
bus_protocols/j1939_handler.h \
|
bus_protocols/j1939_handler.h \
|
||||||
bus_protocols/uds_handler.h \
|
bus_protocols/uds_handler.h \
|
||||||
bus_protocols/isotp_message.h \
|
bus_protocols/isotp_message.h \
|
||||||
jsedit.h
|
jsedit.h \
|
||||||
|
frameplaybackobject.h
|
||||||
|
|
||||||
FORMS += ui/candatagrid.ui \
|
FORMS += ui/candatagrid.ui \
|
||||||
ui/connectionwindow.ui \
|
ui/connectionwindow.ui \
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ QVector<CODE_STRUCT> UDS_COMM_CTRL_SUB = {
|
|||||||
{0,"COMM_NORMAL", "Enable both Rx and Tx of normal messages"},
|
{0,"COMM_NORMAL", "Enable both Rx and Tx of normal messages"},
|
||||||
{1,"COMM_DIS_TX", "Enable reception of normal messages but don't Tx them"},
|
{1,"COMM_DIS_TX", "Enable reception of normal messages but don't Tx them"},
|
||||||
{3,"COMM_DIS_ALL", "Disable both Rx and Tx of non-diagnostics messages"},
|
{3,"COMM_DIS_ALL", "Disable both Rx and Tx of non-diagnostics messages"},
|
||||||
|
{4,"COMM_DIS_TX_ENH", "Addressed bus master should turn off TX on related sub-bus"},
|
||||||
|
{5,"COMM_ENHANC", "Addressed bus master should set related sub-bus to app scheduling mode"},
|
||||||
};
|
};
|
||||||
|
|
||||||
QVector<CODE_STRUCT> UDS_ROUTINE_SUB = {
|
QVector<CODE_STRUCT> UDS_ROUTINE_SUB = {
|
||||||
@@ -319,6 +321,8 @@ QString UDS_HANDLER::getDetailedMessageAnalysis(const UDS_MESSAGE &msg)
|
|||||||
{
|
{
|
||||||
QString buildString;
|
QString buildString;
|
||||||
bool isResponse = true;
|
bool isResponse = true;
|
||||||
|
int dataSize;
|
||||||
|
int addrSize;
|
||||||
|
|
||||||
if (msg.isErrorReply)
|
if (msg.isErrorReply)
|
||||||
{
|
{
|
||||||
@@ -361,9 +365,9 @@ QString UDS_HANDLER::getDetailedMessageAnalysis(const UDS_MESSAGE &msg)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
int p2 = msg.data[1] * 256 + msg.data[2];
|
int p2 = msg.data[1] * 256 + msg.data[2];
|
||||||
buildString.append("\nP2MAX: " + QString::number(p2) + "ms");
|
buildString.append("\nP2MAX (Max Wait / Resp Time): " + QString::number(p2) + "ms");
|
||||||
p2 = (msg.data[3] * 256 + msg.data[4]) * 10;
|
p2 = (msg.data[3] * 256 + msg.data[4]) * 10;
|
||||||
buildString.append("\nP2*MAX: " + QString::number(p2) + "ms");
|
buildString.append("\nP2 Ext MAX: " + QString::number(p2) + "ms");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UDS_SERVICES::ECU_RESET:
|
case UDS_SERVICES::ECU_RESET:
|
||||||
@@ -384,8 +388,15 @@ QString UDS_HANDLER::getDetailedMessageAnalysis(const UDS_MESSAGE &msg)
|
|||||||
else buildString.append("\nNo powerdown time returned");
|
else buildString.append("\nNo powerdown time returned");
|
||||||
break;
|
break;
|
||||||
case UDS_SERVICES::COMM_CTRL:
|
case UDS_SERVICES::COMM_CTRL:
|
||||||
//Comm control has two parameters, sub funct and the next byte should be 1. But it's always one so ignore for now
|
//Comm control has potentially a lot of parameters. control type, comm type, nodeID
|
||||||
buildString.append("Comm type: " + getLongDesc(UDS_COMM_CTRL_SUB, msg.subFunc));
|
buildString.append("Control type: " + getLongDesc(UDS_COMM_CTRL_SUB, msg.subFunc));
|
||||||
|
if (msg.data.length() > 1)
|
||||||
|
buildString.append("\nComm Type: " + QString::number(msg.data[1])); //TODO: no attempt to interpret yet
|
||||||
|
if (msg.data.length() > 3)
|
||||||
|
{
|
||||||
|
int nodeID = (msg.data[2] * 256 + msg.data[3]);
|
||||||
|
buildString.append("\nNode ID: " + Utility::formatHexNum(nodeID));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case UDS_SERVICES::SECURITY_ACCESS:
|
case UDS_SERVICES::SECURITY_ACCESS:
|
||||||
if ((msg.subFunc % 2) == 1)
|
if ((msg.subFunc % 2) == 1)
|
||||||
@@ -423,6 +434,96 @@ QString UDS_HANDLER::getDetailedMessageAnalysis(const UDS_MESSAGE &msg)
|
|||||||
buildString.append("\nECU is now unlocked");
|
buildString.append("\nECU is now unlocked");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case UDS_SERVICES::READ_BY_ID:
|
||||||
|
//parameter is groups of two bytes, each of which specify an ID to read
|
||||||
|
if (msg.data.length() > 2)
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
for (int i = 1; i < msg.data.length(); i = i + 2)
|
||||||
|
{
|
||||||
|
id = (msg.data[i] * 256) + msg.data[i+1];
|
||||||
|
buildString.append("\nID to read: " + Utility::formatHexNum(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::READ_BY_ID + 0x40: //reply
|
||||||
|
buildString.append("Reply is non-standard and so no decoding is done. The format is (ID) followed by how ever much data that ID returns, followed by more ID/data pairs if applicable.\nPayload: ");
|
||||||
|
for (int i = 1; i < msg.data.length(); i++)
|
||||||
|
{
|
||||||
|
buildString.append(Utility::formatHexNum(msg.data[i]) + " ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::READ_BY_ADDR:
|
||||||
|
//subfunc byte specifies address and length format, then address, then size
|
||||||
|
dataSize = msg.subFunc >> 4;
|
||||||
|
addrSize = msg.subFunc & 0xF;
|
||||||
|
if (msg.data.length() > (dataSize + addrSize))
|
||||||
|
{
|
||||||
|
buildString.append("Address: 0x");
|
||||||
|
for (int i = 0; i < addrSize; i++) buildString.append(QString::number(msg.data[1+i], 16).toUpper().rightJustified(2,'0'));
|
||||||
|
buildString.append("\nSize: 0x");
|
||||||
|
for (int i = 0; i < dataSize; i++) buildString.append(QString::number(msg.data[1+i+addrSize], 16).toUpper().rightJustified(2,'0'));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buildString.append("Message has insufficient bytes to properly decode address and size!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::READ_BY_ADDR + 0x40:
|
||||||
|
buildString.append("Reply is a raw packet of data of the size requested.\nPayload: ");
|
||||||
|
for (int i = 1; i < msg.data.length(); i++)
|
||||||
|
{
|
||||||
|
buildString.append(Utility::formatHexNum(msg.data[i]) + " ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::WRITE_BY_ID:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::ROUTINE_CTRL:
|
||||||
|
buildString.append("Routine Control: " + getLongDesc(UDS_ROUTINE_SUB, msg.subFunc));
|
||||||
|
if (msg.data.length() > 2)
|
||||||
|
{
|
||||||
|
int routineID;
|
||||||
|
routineID = (msg.data[1] * 256 + msg.data[2]);
|
||||||
|
buildString.append("\nRoutine ID: " + Utility::formatHexNum(routineID));
|
||||||
|
}
|
||||||
|
if (msg.data.length() > 3)
|
||||||
|
{
|
||||||
|
buildString.append("\nParameter bytes to routine: ");
|
||||||
|
for (int i = 4; i < msg.data.length(); i++)
|
||||||
|
{
|
||||||
|
buildString.append(Utility::formatHexNum(msg.data[i]) + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::ROUTINE_CTRL + 0x40:
|
||||||
|
buildString.append("Routine Control: " + getLongDesc(UDS_ROUTINE_SUB, msg.subFunc));
|
||||||
|
if (msg.data.length() > 2)
|
||||||
|
{
|
||||||
|
int routineID;
|
||||||
|
routineID = (msg.data[1] * 256 + msg.data[2]);
|
||||||
|
buildString.append("\nRoutine ID: " + Utility::formatHexNum(routineID));
|
||||||
|
}
|
||||||
|
if (msg.data.length() > 3)
|
||||||
|
{
|
||||||
|
buildString.append("\nBytes returned by routine: ");
|
||||||
|
for (int i = 4; i < msg.data.length(); i++)
|
||||||
|
{
|
||||||
|
buildString.append(Utility::formatHexNum(msg.data[i]) + " ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::REQUEST_DOWNLOAD:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::REQUEST_UPLOAD:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::TRANSFER_DATA:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::REQ_TRANS_EXIT:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::REQ_FILE_TRANS:
|
||||||
|
break;
|
||||||
|
case UDS_SERVICES::WRITE_BY_ADDR:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ public:
|
|||||||
uint32_t len;
|
uint32_t len;
|
||||||
unsigned char data[8];
|
unsigned char data[8];
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
|
|
||||||
|
friend bool operator<(const CANFrame& l, const CANFrame& r)
|
||||||
|
{
|
||||||
|
return l.timestamp < r.timestamp;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CANFltObserver
|
class CANFltObserver
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONFIG
|
#ifndef CONFIG
|
||||||
#define CONFIG
|
#define CONFIG
|
||||||
|
|
||||||
#define VERSION 178
|
#define VERSION 179
|
||||||
|
|
||||||
//try to keep this in sync.
|
//try to keep this in sync.
|
||||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QDebug>
|
||||||
#include "canbus.h"
|
#include "canbus.h"
|
||||||
|
|
||||||
CANBus::CANBus()
|
CANBus::CANBus()
|
||||||
@@ -25,18 +26,22 @@ bool CANBus::operator==(const CANBus& bus) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CANBus::setSpeed(int newSpeed){
|
void CANBus::setSpeed(int newSpeed){
|
||||||
|
//qDebug() << "CANBUS SetSpeed = " << newSpeed;
|
||||||
speed = newSpeed;
|
speed = newSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANBus::setListenOnly(bool mode){
|
void CANBus::setListenOnly(bool mode){
|
||||||
|
//qDebug() << "CANBUS SetListenOnly = " << mode;
|
||||||
listenOnly = mode;
|
listenOnly = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANBus::setSingleWire(bool mode){
|
void CANBus::setSingleWire(bool mode){
|
||||||
|
//qDebug() << "CANBUS SetSingleWire = " << mode;
|
||||||
singleWire = mode;
|
singleWire = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANBus::setEnabled(bool mode){
|
void CANBus::setEnabled(bool mode){
|
||||||
|
//qDebug() << "CANBUS SetEnabled = " << mode;
|
||||||
active = mode;
|
active = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef CANBus_H
|
#ifndef CANBus_H
|
||||||
#define CANBus_H
|
#define CANBus_H
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
#include "can_structs.h"
|
||||||
|
|
||||||
class CANBus
|
class CANBus
|
||||||
{
|
{
|
||||||
@@ -31,4 +32,10 @@ QDataStream & operator>>(QDataStream & pStream, CANBus& pCanBus);
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(CANBus);
|
Q_DECLARE_METATYPE(CANBus);
|
||||||
|
|
||||||
|
struct BusData {
|
||||||
|
CANBus mBus;
|
||||||
|
bool mConfigured;
|
||||||
|
QVector<CANFltObserver> mTargettedFrames;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CANBus_H
|
#endif // CANBus_H
|
||||||
|
|||||||
@@ -21,4 +21,11 @@ namespace CANCon {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CANConStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CANCon::status conStatus;
|
||||||
|
int numHardwareBuses;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // CANCONCONST_H
|
#endif // CANCONCONST_H
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ CANConManager::CANConManager(QObject *parent): QObject(parent)
|
|||||||
void CANConManager::resetTimeBasis()
|
void CANConManager::resetTimeBasis()
|
||||||
{
|
{
|
||||||
mTimestampBasis = QDateTime::currentMSecsSinceEpoch() * 1000;
|
mTimestampBasis = QDateTime::currentMSecsSinceEpoch() * 1000;
|
||||||
|
mElapsedTimer.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
CANConManager::~CANConManager()
|
CANConManager::~CANConManager()
|
||||||
@@ -182,8 +183,15 @@ bool CANConManager::sendFrame(const CANFrame& pFrame)
|
|||||||
{
|
{
|
||||||
workingFrame.bus -= busBase;
|
workingFrame.bus -= busBase;
|
||||||
workingFrame.isReceived = false;
|
workingFrame.isReceived = false;
|
||||||
workingFrame.timestamp = (QDateTime::currentMSecsSinceEpoch() * 1000);
|
if (useSystemTime)
|
||||||
if (!useSystemTime) workingFrame.timestamp -= mTimestampBasis;
|
{
|
||||||
|
workingFrame.timestamp = (QDateTime::currentMSecsSinceEpoch() * 1000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
workingFrame.timestamp = mElapsedTimer.nsecsElapsed() / 1000;
|
||||||
|
//workingFrame.timestamp -= mTimestampBasis;
|
||||||
|
}
|
||||||
txFrame = conn->getQueue().get();
|
txFrame = conn->getQueue().get();
|
||||||
*txFrame = workingFrame;
|
*txFrame = workingFrame;
|
||||||
conn->getQueue().queue();
|
conn->getQueue().queue();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
|
||||||
#include "canconnection.h"
|
#include "canconnection.h"
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ private:
|
|||||||
static CANConManager* mInstance;
|
static CANConManager* mInstance;
|
||||||
QList<CANConnection*> mConns;
|
QList<CANConnection*> mConns;
|
||||||
QTimer mTimer;
|
QTimer mTimer;
|
||||||
|
QElapsedTimer mElapsedTimer;
|
||||||
uint64_t mTimestampBasis;
|
uint64_t mTimestampBasis;
|
||||||
uint32_t mNumActiveBuses;
|
uint32_t mNumActiveBuses;
|
||||||
bool useSystemTime;
|
bool useSystemTime;
|
||||||
|
|||||||
@@ -2,14 +2,6 @@
|
|||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include "canconnection.h"
|
#include "canconnection.h"
|
||||||
|
|
||||||
|
|
||||||
struct BusData {
|
|
||||||
CANBus mBus;
|
|
||||||
bool mConfigured;
|
|
||||||
QVector<CANFltObserver> mTargettedFrames;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
CANConnection::CANConnection(QString pPort,
|
CANConnection::CANConnection(QString pPort,
|
||||||
CANCon::type pType,
|
CANCon::type pType,
|
||||||
int pNumBuses,
|
int pNumBuses,
|
||||||
@@ -27,7 +19,7 @@ CANConnection::CANConnection(QString pPort,
|
|||||||
/* register types */
|
/* register types */
|
||||||
qRegisterMetaType<CANBus>("CANBus");
|
qRegisterMetaType<CANBus>("CANBus");
|
||||||
qRegisterMetaType<CANFrame>("CANFrame");
|
qRegisterMetaType<CANFrame>("CANFrame");
|
||||||
qRegisterMetaType<CANCon::status>("CANCon::status");
|
qRegisterMetaType<CANConStatus>("CANConStatus");
|
||||||
qRegisterMetaType<CANFltObserver>("CANFlt");
|
qRegisterMetaType<CANFltObserver>("CANFlt");
|
||||||
|
|
||||||
/* set queue size */
|
/* set queue size */
|
||||||
@@ -35,9 +27,9 @@ CANConnection::CANConnection(QString pPort,
|
|||||||
|
|
||||||
/* allocate buses */
|
/* allocate buses */
|
||||||
/* TODO: change those tables for a vector */
|
/* TODO: change those tables for a vector */
|
||||||
mBusData_p = new BusData[mNumBuses];
|
mBusData.resize(mNumBuses);
|
||||||
for(int i=0 ; i<mNumBuses ; i++) {
|
for(int i=0 ; i<mNumBuses ; i++) {
|
||||||
mBusData_p[i].mConfigured = false;
|
mBusData[i].mConfigured = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if needed, create a thread and move ourself into it */
|
/* if needed, create a thread and move ourself into it */
|
||||||
@@ -57,10 +49,7 @@ CANConnection::~CANConnection()
|
|||||||
mThread_p = NULL;
|
mThread_p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mBusData_p) {
|
mBusData.clear();
|
||||||
delete[] mBusData_p;
|
|
||||||
mBusData_p = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -206,13 +195,13 @@ int CANConnection::getNumBuses() const{
|
|||||||
bool CANConnection::isConfigured(int pBusId) {
|
bool CANConnection::isConfigured(int pBusId) {
|
||||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||||
return false;
|
return false;
|
||||||
return mBusData_p[pBusId].mConfigured;
|
return mBusData[pBusId].mConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANConnection::setConfigured(int pBusId, bool pConfigured) {
|
void CANConnection::setConfigured(int pBusId, bool pConfigured) {
|
||||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||||
return;
|
return;
|
||||||
mBusData_p[pBusId].mConfigured = pConfigured;
|
mBusData[pBusId].mConfigured = pConfigured;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -220,7 +209,7 @@ bool CANConnection::getBusConfig(int pBusId, CANBus& pBus) {
|
|||||||
if( pBusId < 0 || pBusId >= getNumBuses() || !isConfigured(pBusId))
|
if( pBusId < 0 || pBusId >= getNumBuses() || !isConfigured(pBusId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
pBus = mBusData_p[pBusId].mBus;
|
pBus = mBusData[pBusId].mBus;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,8 +218,8 @@ void CANConnection::setBusConfig(int pBusId, CANBus& pBus) {
|
|||||||
if( pBusId < 0 || pBusId >= getNumBuses())
|
if( pBusId < 0 || pBusId >= getNumBuses())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mBusData_p[pBusId].mConfigured = true;
|
mBusData[pBusId].mConfigured = true;
|
||||||
mBusData_p[pBusId].mBus = pBus;
|
mBusData[pBusId].mBus = pBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -293,7 +282,7 @@ bool CANConnection::addTargettedFrame(int pBusId, uint32_t ID, uint32_t mask, QO
|
|||||||
target.id = ID;
|
target.id = ID;
|
||||||
target.mask = mask;
|
target.mask = mask;
|
||||||
target.observer = receiver;
|
target.observer = receiver;
|
||||||
mBusData_p[pBusId].mTargettedFrames.append(target);
|
mBusData[pBusId].mTargettedFrames.append(target);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -321,7 +310,7 @@ bool CANConnection::removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask,
|
|||||||
target.id = ID;
|
target.id = ID;
|
||||||
target.mask = mask;
|
target.mask = mask;
|
||||||
target.observer = receiver;
|
target.observer = receiver;
|
||||||
mBusData_p[pBusId].mTargettedFrames.removeAll(target);
|
mBusData[pBusId].mTargettedFrames.removeAll(target);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -329,9 +318,9 @@ bool CANConnection::removeTargettedFrame(int pBusId, uint32_t ID, uint32_t mask,
|
|||||||
bool CANConnection::removeAllTargettedFrames(QObject *receiver)
|
bool CANConnection::removeAllTargettedFrames(QObject *receiver)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < getNumBuses(); i++) {
|
for (int i = 0; i < getNumBuses(); i++) {
|
||||||
foreach (const CANFltObserver filt, mBusData_p[i].mTargettedFrames)
|
foreach (const CANFltObserver filt, mBusData[i].mTargettedFrames)
|
||||||
{
|
{
|
||||||
if (filt.observer == receiver) mBusData_p[i].mTargettedFrames.removeOne(filt);
|
if (filt.observer == receiver) mBusData[i].mTargettedFrames.removeOne(filt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,10 +331,10 @@ void CANConnection::checkTargettedFrame(CANFrame &frame)
|
|||||||
{
|
{
|
||||||
unsigned int maskedID;
|
unsigned int maskedID;
|
||||||
//qDebug() << "Got frame with ID " << frame.ID << " on bus " << frame.bus;
|
//qDebug() << "Got frame with ID " << frame.ID << " on bus " << frame.bus;
|
||||||
if (mBusData_p == 0) return;
|
if (mBusData.count() == 0) return;
|
||||||
|
|
||||||
if (mBusData_p[frame.bus].mTargettedFrames.length() == 0) return;
|
if (mBusData[frame.bus].mTargettedFrames.length() == 0) return;
|
||||||
foreach (const CANFltObserver filt, mBusData_p[frame.bus].mTargettedFrames)
|
foreach (const CANFltObserver filt, mBusData[frame.bus].mTargettedFrames)
|
||||||
{
|
{
|
||||||
//qDebug() << "Checking filter with id " << filt.id << " mask " << filt.mask;
|
//qDebug() << "Checking filter with id " << filt.id << " mask " << filt.mask;
|
||||||
maskedID = frame.ID & filt.mask;
|
maskedID = frame.ID & filt.mask;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ signals:
|
|||||||
* @brief event emitted when the CANCon::status of the connection changes (connected->not_connected or the other way round)
|
* @brief event emitted when the CANCon::status of the connection changes (connected->not_connected or the other way round)
|
||||||
* @param pStatus: the new status of the device
|
* @param pStatus: the new status of the device
|
||||||
*/
|
*/
|
||||||
void status(CANCon::status pStatus);
|
void status(CANConStatus pStatus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Event sent when device has done something worthy of debugging output.
|
* @brief Event sent when device has done something worthy of debugging output.
|
||||||
@@ -183,7 +183,8 @@ public slots:
|
|||||||
void debugInput(QByteArray bytes);
|
void debugInput(QByteArray bytes);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int mNumBuses; //protected to allow connected device to figure out how many buses are available
|
int mNumBuses; //protected to allow connected device to figure out how many buses are available
|
||||||
|
QVector<BusData> mBusData;
|
||||||
|
|
||||||
//determine if the passed frame is part of a filter or not.
|
//determine if the passed frame is part of a filter or not.
|
||||||
void checkTargettedFrame(CANFrame &frame);
|
void checkTargettedFrame(CANFrame &frame);
|
||||||
@@ -297,7 +298,6 @@ private:
|
|||||||
bool mIsCapSuspended;
|
bool mIsCapSuspended;
|
||||||
QAtomicInt mStatus;
|
QAtomicInt mStatus;
|
||||||
bool mStarted;
|
bool mStarted;
|
||||||
BusData* mBusData_p;
|
|
||||||
QThread* mThread_p;
|
QThread* mThread_p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation
|
|||||||
return QString(tr("Single Wire"));
|
return QString(tr("Single Wire"));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
return QString(tr("Status"));
|
return QString(tr("Active"));
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
return QString(tr("Active"));
|
return QString(tr("Status"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,10 @@ QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
return 7;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -66,32 +65,99 @@ int CANConnectionModel::rowCount(const QModelIndex &parent) const
|
|||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
|
|
||||||
int rows=0;
|
int rows = 0;
|
||||||
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
QList<CANConnection*>& conns = CANConManager::getInstance()->getConnections();
|
||||||
|
|
||||||
foreach(const CANConnection* conn_p, conns)
|
foreach(const CANConnection* conn_p, conns)
|
||||||
rows+=conn_p->getNumBuses();
|
rows += conn_p->getNumBuses();
|
||||||
|
|
||||||
|
//qDebug() << "Num Rows: " << rows;
|
||||||
|
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags CANConnectionModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return Qt::ItemFlag::NoItemFlags;
|
||||||
|
|
||||||
|
int busId;
|
||||||
|
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||||
|
if (!conn_p) return Qt::ItemFlag::NoItemFlags;
|
||||||
|
|
||||||
|
//you can't set speed, single wire, or listen only on socketcan devices so
|
||||||
|
//detect if we're using GVRET where you can and turn that functionality on
|
||||||
|
bool editParams = false;
|
||||||
|
if (conn_p->getType() == CANCon::GVRET_SERIAL) editParams = true;
|
||||||
|
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 3: //speed
|
||||||
|
if (editParams) return Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsEnabled;
|
||||||
|
else return Qt::ItemFlag::NoItemFlags;
|
||||||
|
break;
|
||||||
|
case 4: //listen only
|
||||||
|
case 5: //single wire
|
||||||
|
if (editParams) return Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsUserCheckable;
|
||||||
|
else return Qt::ItemFlag::NoItemFlags;
|
||||||
|
break;
|
||||||
|
case 6: //enabled
|
||||||
|
return Qt::ItemFlag::ItemIsEditable | Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsUserCheckable;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return Qt::ItemFlag::ItemIsEnabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CANConnectionModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
qDebug() << "setData: " << index.row() << ":" << index.column() << " role: " << role << " Val: " << value;
|
||||||
|
|
||||||
|
int busId;
|
||||||
|
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||||
|
if (!conn_p) return false;
|
||||||
|
CANBus bus;
|
||||||
|
bool ret;
|
||||||
|
ret = conn_p->getBusSettings(busId, bus);
|
||||||
|
if (!ret) return false;
|
||||||
|
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 3: //speed
|
||||||
|
bus.speed = value.toInt();
|
||||||
|
break;
|
||||||
|
case 4: //listen only
|
||||||
|
bus.listenOnly = value.toBool();
|
||||||
|
break;
|
||||||
|
case 5: //single wire
|
||||||
|
bus.singleWire = value.toBool();
|
||||||
|
break;
|
||||||
|
case 6: //active
|
||||||
|
bus.active = value.toBool();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
conn_p->setBusSettings(busId, bus);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
//qDebug() << "Row: " << index.row();
|
||||||
|
|
||||||
|
int busId;
|
||||||
|
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||||
|
CANBus bus;
|
||||||
|
bool ret;
|
||||||
|
if (!conn_p) return QVariant();
|
||||||
|
ret = conn_p->getBusSettings(busId, bus);
|
||||||
|
bool isSocketCAN = (conn_p->getType() == CANCon::SOCKETCAN) ? true: false;
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
//qDebug() << "ConnP: " << conn_p << " ret " << ret;
|
||||||
int busId;
|
|
||||||
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
|
||||||
if(!conn_p)
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
CANBus bus;
|
if (role == Qt::DisplayRole) {
|
||||||
bool ret;
|
|
||||||
ret = conn_p->getBusSettings(busId, bus);
|
|
||||||
if(!ret) return QVariant();
|
|
||||||
|
|
||||||
switch (index.column())
|
switch (index.column())
|
||||||
{
|
{
|
||||||
@@ -114,18 +180,35 @@ QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
|||||||
else qDebug() << "Tried to show connection port but connection was NULL";
|
else qDebug() << "Tried to show connection port but connection was NULL";
|
||||||
break;
|
break;
|
||||||
case 3: //speed
|
case 3: //speed
|
||||||
return QString::number(bus.speed);
|
if(!ret) return QVariant();
|
||||||
|
if (!isSocketCAN) return QString::number(bus.speed);
|
||||||
|
else return QString("N/A");
|
||||||
case 4: //Listen Only
|
case 4: //Listen Only
|
||||||
return (bus.listenOnly) ? "True" : "False";
|
return QVariant();
|
||||||
case 5: //Single Wire
|
case 5: //Single Wire
|
||||||
return (bus.singleWire) ? "True" : "False";
|
return QVariant();
|
||||||
case 6: //Status
|
case 6: //Status
|
||||||
return (conn_p->getStatus()==CANCon::CONNECTED) ? "Connected" : "Not Connected";
|
return QVariant();
|
||||||
case 7: //Active
|
case 7: //Active
|
||||||
return (bus.active) ? "True" : "False";
|
return (conn_p->getStatus()==CANCon::CONNECTED) ? "Connected" : "Not Connected";
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (role == Qt::CheckStateRole)
|
||||||
|
{
|
||||||
|
switch (index.column())
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
return (bus.listenOnly) ? Qt::Checked : Qt::Unchecked;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
return (bus.singleWire) ? Qt::Checked : Qt::Unchecked;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
return (bus.active) ? Qt::Checked : Qt::Unchecked;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@@ -172,9 +255,11 @@ CANConnection* CANConnectionModel::getAtIdx(int pIdx, int& pBusId) const
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CANConnectionModel::refresh(int pIndex)
|
void CANConnectionModel::refresh(int pIndex)
|
||||||
{
|
{
|
||||||
|
beginResetModel();
|
||||||
|
endResetModel();
|
||||||
|
/*
|
||||||
QModelIndex begin;
|
QModelIndex begin;
|
||||||
QModelIndex end;
|
QModelIndex end;
|
||||||
|
|
||||||
@@ -186,5 +271,5 @@ void CANConnectionModel::refresh(int pIndex)
|
|||||||
begin = createIndex(0, 0);
|
begin = createIndex(0, 0);
|
||||||
end = createIndex(rowCount()-1, columnCount()-1);
|
end = createIndex(rowCount()-1, columnCount()-1);
|
||||||
}
|
}
|
||||||
dataChanged(begin, end, QVector<int>(Qt::DisplayRole));
|
dataChanged(begin, end, QVector<int>(Qt::DisplayRole)); */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ public:
|
|||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
void add(CANConnection* pConn_p);
|
void add(CANConnection* pConn_p);
|
||||||
|
|||||||
@@ -24,25 +24,17 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
|||||||
|
|
||||||
connModel = new CANConnectionModel(this);
|
connModel = new CANConnectionModel(this);
|
||||||
ui->tableConnections->setModel(connModel);
|
ui->tableConnections->setModel(connModel);
|
||||||
ui->tableConnections->setColumnWidth(0, 50);
|
ui->tableConnections->setColumnWidth(0, 40);
|
||||||
ui->tableConnections->setColumnWidth(1, 110);
|
ui->tableConnections->setColumnWidth(1, 70);
|
||||||
ui->tableConnections->setColumnWidth(2, 110);
|
ui->tableConnections->setColumnWidth(2, 70);
|
||||||
ui->tableConnections->setColumnWidth(3, 110);
|
ui->tableConnections->setColumnWidth(3, 70);
|
||||||
ui->tableConnections->setColumnWidth(4, 75);
|
ui->tableConnections->setColumnWidth(4, 70);
|
||||||
ui->tableConnections->setColumnWidth(5, 75);
|
ui->tableConnections->setColumnWidth(5, 70);
|
||||||
ui->tableConnections->setColumnWidth(6, 75);
|
ui->tableConnections->setColumnWidth(6, 70);
|
||||||
ui->tableConnections->setColumnWidth(7, 75);
|
ui->tableConnections->setColumnWidth(7, 90);
|
||||||
QHeaderView *HorzHdr = ui->tableConnections->horizontalHeader();
|
QHeaderView *HorzHdr = ui->tableConnections->horizontalHeader();
|
||||||
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
HorzHdr->setStretchLastSection(true); //causes the data column to automatically fill the tableview
|
||||||
|
|
||||||
ui->ckSingleWire->setChecked(settings.value("Main/SingleWireMode", false).toBool());
|
|
||||||
|
|
||||||
ui->cbSpeed->addItem(tr("125000"));
|
|
||||||
ui->cbSpeed->addItem(tr("250000"));
|
|
||||||
ui->cbSpeed->addItem(tr("500000"));
|
|
||||||
ui->cbSpeed->addItem(tr("1000000"));
|
|
||||||
ui->cbSpeed->addItem(tr("33333"));
|
|
||||||
|
|
||||||
ui->textConsole->setEnabled(false);
|
ui->textConsole->setEnabled(false);
|
||||||
ui->btnClearDebug->setEnabled(false);
|
ui->btnClearDebug->setEnabled(false);
|
||||||
ui->btnSendHex->setEnabled(false);
|
ui->btnSendHex->setEnabled(false);
|
||||||
@@ -61,9 +53,7 @@ ConnectionWindow::ConnectionWindow(QWidget *parent) :
|
|||||||
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbGVRET, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->rbKvaser, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbKvaser, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbSocketCAN, &QAbstractButton::clicked, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->btnRevert, &QPushButton::clicked, this, &ConnectionWindow::handleRevert);
|
|
||||||
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
|
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &ConnectionWindow::currentRowChanged);
|
||||||
connect(ui->btnNewConn, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn);
|
|
||||||
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
||||||
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
||||||
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
||||||
@@ -100,6 +90,7 @@ void ConnectionWindow::showEvent(QShowEvent* event)
|
|||||||
readSettings();
|
readSettings();
|
||||||
ui->tableConnections->selectRow(0);
|
ui->tableConnections->selectRow(0);
|
||||||
currentRowChanged(ui->tableConnections->currentIndex(), ui->tableConnections->currentIndex());
|
currentRowChanged(ui->tableConnections->currentIndex(), ui->tableConnections->currentIndex());
|
||||||
|
handleConnTypeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::closeEvent(QCloseEvent *event)
|
void ConnectionWindow::closeEvent(QCloseEvent *event)
|
||||||
@@ -207,7 +198,7 @@ void ConnectionWindow::handleConnTypeChanged()
|
|||||||
|
|
||||||
|
|
||||||
/* status */
|
/* status */
|
||||||
void ConnectionWindow::connectionStatus(CANCon::status pStatus)
|
void ConnectionWindow::connectionStatus(CANConStatus pStatus)
|
||||||
{
|
{
|
||||||
Q_UNUSED(pStatus);
|
Q_UNUSED(pStatus);
|
||||||
|
|
||||||
@@ -218,53 +209,14 @@ void ConnectionWindow::connectionStatus(CANCon::status pStatus)
|
|||||||
|
|
||||||
void ConnectionWindow::handleOKButton()
|
void ConnectionWindow::handleOKButton()
|
||||||
{
|
{
|
||||||
int whichRow = ui->tableConnections->selectionModel()->currentIndex().row();
|
|
||||||
|
|
||||||
CANConnection* conn_p = NULL;
|
CANConnection* conn_p = NULL;
|
||||||
|
|
||||||
if (whichRow > -1)
|
if( ! CANConManager::getInstance()->getByName(getPortName()) )
|
||||||
{
|
|
||||||
/* set information for selected connection */
|
|
||||||
int busId;
|
|
||||||
CANBus bus;
|
|
||||||
bool ret;
|
|
||||||
|
|
||||||
conn_p = connModel->getAtIdx(whichRow, busId);
|
|
||||||
if(!conn_p) return;
|
|
||||||
|
|
||||||
ret = conn_p->getBusSettings(busId, bus);
|
|
||||||
if(!ret) return;
|
|
||||||
|
|
||||||
|
|
||||||
bus.setListenOnly(ui->ckListenOnly->isChecked());
|
|
||||||
bus.setSingleWire(ui->ckSingleWire->isChecked());
|
|
||||||
bus.setEnabled(ui->ckEnabled->isChecked());
|
|
||||||
bus.setSpeed(ui->cbSpeed->currentText().toInt());
|
|
||||||
/* update bus settings */
|
|
||||||
conn_p->setBusSettings(busId, bus);
|
|
||||||
|
|
||||||
connModel->refresh(whichRow);
|
|
||||||
}
|
|
||||||
else if( ! CANConManager::getInstance()->getByName(getPortName()) )
|
|
||||||
{
|
{
|
||||||
/* create connection */
|
/* create connection */
|
||||||
conn_p = create(getConnectionType(), getPortName());
|
conn_p = create(getConnectionType(), getPortName());
|
||||||
if(!conn_p)
|
if(!conn_p)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i=0 ; i<conn_p->getNumBuses() ; i++) {
|
|
||||||
/* set bus configuration */
|
|
||||||
CANBus bus;
|
|
||||||
bus.active = ui->ckEnabled->isChecked();
|
|
||||||
bus.listenOnly = ui->ckListenOnly->isChecked();
|
|
||||||
bus.singleWire = ui->ckSingleWire->isChecked();
|
|
||||||
|
|
||||||
bus.speed = ui->cbSpeed->currentText().toInt();
|
|
||||||
|
|
||||||
/* update bus settings */
|
|
||||||
conn_p->setBusSettings(i, bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add connection to model */
|
/* add connection to model */
|
||||||
connModel->add(conn_p);
|
connModel->add(conn_p);
|
||||||
}
|
}
|
||||||
@@ -280,6 +232,7 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
|
|
||||||
disconnect(connModel->getAtIdx(previous.row(), busId), SIGNAL(debugOutput(QString)), 0, 0);
|
disconnect(connModel->getAtIdx(previous.row(), busId), SIGNAL(debugOutput(QString)), 0, 0);
|
||||||
disconnect(this, SIGNAL(sendDebugData(QByteArray)), connModel->getAtIdx(previous.row(), busId), SLOT(debugInput(QByteArray)));
|
disconnect(this, SIGNAL(sendDebugData(QByteArray)), connModel->getAtIdx(previous.row(), busId), SLOT(debugInput(QByteArray)));
|
||||||
|
return;
|
||||||
|
|
||||||
/* enable / diable connection type */
|
/* enable / diable connection type */
|
||||||
ui->stPort->setEnabled(selIdx==-1);
|
ui->stPort->setEnabled(selIdx==-1);
|
||||||
@@ -291,9 +244,6 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
{
|
{
|
||||||
ui->btnOK->setText(tr("Create New Connection"));
|
ui->btnOK->setText(tr("Create New Connection"));
|
||||||
ui->rbGVRET->setChecked(true);
|
ui->rbGVRET->setChecked(true);
|
||||||
ui->ckListenOnly->setChecked(false);
|
|
||||||
ui->ckSingleWire->setChecked(false);
|
|
||||||
ui->ckEnabled->setChecked(false);
|
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
setPortName(CANCon::GVRET_SERIAL, "");
|
setPortName(CANCon::GVRET_SERIAL, "");
|
||||||
}
|
}
|
||||||
@@ -313,9 +263,6 @@ void ConnectionWindow::currentRowChanged(const QModelIndex ¤t, const QMode
|
|||||||
if(!ret) return;
|
if(!ret) return;
|
||||||
|
|
||||||
ui->btnOK->setText(tr("Update Connection Settings"));
|
ui->btnOK->setText(tr("Update Connection Settings"));
|
||||||
ui->ckListenOnly->setChecked(bus.isListenOnly());
|
|
||||||
ui->ckSingleWire->setChecked(bus.isSingleWire());
|
|
||||||
ui->ckEnabled->setChecked(bus.isActive());
|
|
||||||
setSpeed(bus.getSpeed());
|
setSpeed(bus.getSpeed());
|
||||||
setPortName(conn_p->getType(), conn_p->getPort());
|
setPortName(conn_p->getType(), conn_p->getPort());
|
||||||
}
|
}
|
||||||
@@ -349,7 +296,6 @@ void ConnectionWindow::selectSerial()
|
|||||||
{
|
{
|
||||||
/* set combobox page visible */
|
/* set combobox page visible */
|
||||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||||
ui->cbSpeed->setEnabled(true);
|
|
||||||
|
|
||||||
ui->cbPort->clear();
|
ui->cbPort->clear();
|
||||||
ports = QSerialPortInfo::availablePorts();
|
ports = QSerialPortInfo::availablePorts();
|
||||||
@@ -362,7 +308,6 @@ void ConnectionWindow::selectKvaser()
|
|||||||
{
|
{
|
||||||
/* set combobox page visible */
|
/* set combobox page visible */
|
||||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||||
ui->cbSpeed->setEnabled(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::selectSocketCan()
|
void ConnectionWindow::selectSocketCan()
|
||||||
@@ -373,18 +318,6 @@ void ConnectionWindow::selectSocketCan()
|
|||||||
|
|
||||||
void ConnectionWindow::setSpeed(int speed0)
|
void ConnectionWindow::setSpeed(int speed0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < ui->cbSpeed->count(); i++)
|
|
||||||
{
|
|
||||||
if (ui->cbSpeed->itemText(i).toInt() == speed0)
|
|
||||||
{
|
|
||||||
ui->cbSpeed->setCurrentIndex(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add custom speed */
|
|
||||||
ui->cbSpeed->addItem(QString::number(speed0));
|
|
||||||
ui->cbSpeed->setCurrentIndex(ui->cbSpeed->count() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
||||||
@@ -393,9 +326,6 @@ void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
|||||||
{
|
{
|
||||||
case CANCon::GVRET_SERIAL:
|
case CANCon::GVRET_SERIAL:
|
||||||
ui->rbGVRET->setChecked(true);
|
ui->rbGVRET->setChecked(true);
|
||||||
ui->cbSpeed->setEnabled(true);
|
|
||||||
ui->ckListenOnly->setEnabled(true);
|
|
||||||
ui->ckSingleWire->setEnabled(true);
|
|
||||||
break;
|
break;
|
||||||
case CANCon::KVASER:
|
case CANCon::KVASER:
|
||||||
ui->rbKvaser->setChecked(true);
|
ui->rbKvaser->setChecked(true);
|
||||||
@@ -403,9 +333,6 @@ void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
|||||||
case CANCon::SOCKETCAN:
|
case CANCon::SOCKETCAN:
|
||||||
ui->rbSocketCAN->setChecked(true);
|
ui->rbSocketCAN->setChecked(true);
|
||||||
//you can't configure any of the below three with socketcan so dim them out
|
//you can't configure any of the below three with socketcan so dim them out
|
||||||
ui->cbSpeed->setEnabled(false);
|
|
||||||
ui->ckListenOnly->setEnabled(false);
|
|
||||||
ui->ckSingleWire->setEnabled(false);
|
|
||||||
break;
|
break;
|
||||||
default: {}
|
default: {}
|
||||||
}
|
}
|
||||||
@@ -435,16 +362,6 @@ void ConnectionWindow::setPortName(CANCon::type pType, QString pPortName)
|
|||||||
//-1 means leave it at whatever it booted up to. 0 means disable. Otherwise the actual rate we want.
|
//-1 means leave it at whatever it booted up to. 0 means disable. Otherwise the actual rate we want.
|
||||||
int ConnectionWindow::getSpeed()
|
int ConnectionWindow::getSpeed()
|
||||||
{
|
{
|
||||||
switch (ui->cbSpeed->currentIndex())
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
case 0:
|
|
||||||
return -1;
|
|
||||||
case 1:
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return (ui->cbSpeed->currentText().toInt());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ConnectionWindow::getPortName()
|
QString ConnectionWindow::getPortName()
|
||||||
@@ -475,12 +392,10 @@ CANCon::type ConnectionWindow::getConnectionType()
|
|||||||
|
|
||||||
void ConnectionWindow::setSWMode(bool mode)
|
void ConnectionWindow::setSWMode(bool mode)
|
||||||
{
|
{
|
||||||
ui->ckSingleWire->setChecked(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectionWindow::getSWMode()
|
bool ConnectionWindow::getSWMode()
|
||||||
{
|
{
|
||||||
if (ui->ckSingleWire->checkState() == Qt::Checked) return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,8 +445,8 @@ CANConnection* ConnectionWindow::create(CANCon::type pTye, QString pPortName)
|
|||||||
if(conn_p)
|
if(conn_p)
|
||||||
{
|
{
|
||||||
/* connect signal */
|
/* connect signal */
|
||||||
connect(conn_p, SIGNAL(status(CANCon::status)),
|
connect(conn_p, SIGNAL(status(CANConStatus)),
|
||||||
this, SLOT(connectionStatus(CANCon::status)));
|
this, SLOT(connectionStatus(CANConStatus)));
|
||||||
|
|
||||||
/*TODO add return value and checks */
|
/*TODO add return value and checks */
|
||||||
conn_p->start();
|
conn_p->start();
|
||||||
@@ -552,17 +467,10 @@ void ConnectionWindow::loadConnections()
|
|||||||
/* fill connection list */
|
/* fill connection list */
|
||||||
QVector<QString> portNames = settings.value("connections/portNames").value<QVector<QString>>();
|
QVector<QString> portNames = settings.value("connections/portNames").value<QVector<QString>>();
|
||||||
QVector<int> devTypes = settings.value("connections/types").value<QVector<int>>();
|
QVector<int> devTypes = settings.value("connections/types").value<QVector<int>>();
|
||||||
QList<CANBus> busses = settings.value("connections/busses").value<QList<CANBus>>();
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0 ; i<portNames.count() ; i++)
|
for(int i=0 ; i<portNames.count() ; i++)
|
||||||
{
|
{
|
||||||
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i]);
|
CANConnection* conn_p = create((CANCon::type)devTypes[i], portNames[i]);
|
||||||
if(conn_p)
|
|
||||||
{
|
|
||||||
for(int j=0 ; j<conn_p->getNumBuses() ; j++)
|
|
||||||
conn_p->setBusSettings(j, busses.takeFirst());
|
|
||||||
}
|
|
||||||
/* add connection to model */
|
/* add connection to model */
|
||||||
connModel->add(conn_p);
|
connModel->add(conn_p);
|
||||||
}
|
}
|
||||||
@@ -579,23 +487,14 @@ void ConnectionWindow::saveConnections()
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
QVector<QString> portNames;
|
QVector<QString> portNames;
|
||||||
QVector<int> devTypes;
|
QVector<int> devTypes;
|
||||||
QList<CANBus> busses;
|
|
||||||
|
|
||||||
/* save connections */
|
/* save connections */
|
||||||
foreach(CANConnection* conn_p, conns)
|
foreach(CANConnection* conn_p, conns)
|
||||||
{
|
{
|
||||||
portNames.append(conn_p->getPort());
|
portNames.append(conn_p->getPort());
|
||||||
devTypes.append(conn_p->getType());
|
devTypes.append(conn_p->getType());
|
||||||
|
|
||||||
for(int i=0 ; i<conn_p->getNumBuses() ; i++)
|
|
||||||
{
|
|
||||||
CANBus bus;
|
|
||||||
conn_p->getBusSettings(i, bus);
|
|
||||||
busses.append(bus);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
settings.setValue("connections/portNames", QVariant::fromValue(portNames));
|
||||||
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
settings.setValue("connections/types", QVariant::fromValue(devTypes));
|
||||||
settings.setValue("connections/busses", QVariant::fromValue(busses));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ private slots:
|
|||||||
void handleClearDebugText();
|
void handleClearDebugText();
|
||||||
void handleSendHex();
|
void handleSendHex();
|
||||||
void handleSendText();
|
void handleSendText();
|
||||||
void connectionStatus(CANCon::status);
|
void connectionStatus(CANConStatus);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ConnectionWindow *ui;
|
Ui::ConnectionWindow *ui;
|
||||||
|
|||||||
+174
-26
@@ -125,25 +125,71 @@ void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus)
|
|||||||
}
|
}
|
||||||
else deviceSingleWireMode = 0;
|
else deviceSingleWireMode = 0;
|
||||||
}
|
}
|
||||||
|
else if (pBusIdx == 2)
|
||||||
|
{
|
||||||
|
swcanBaud = bus.getSpeed();
|
||||||
|
swcanBaud |= 0x80000000;
|
||||||
|
if (bus.isActive())
|
||||||
|
{
|
||||||
|
swcanBaud |= 0x40000000;
|
||||||
|
swcanEnabled = true;
|
||||||
|
}
|
||||||
|
else swcanEnabled = false;
|
||||||
|
|
||||||
/* update baud rates */
|
if (bus.isListenOnly())
|
||||||
QByteArray buffer;
|
{
|
||||||
qDebug() << "Got signal to update bauds. 1: " << can0Baud <<" 2: " << can1Baud;
|
swcanBaud |= 0x20000000;
|
||||||
debugOutput("Got signal to update bauds. 1: " + QString::number(can0Baud) + " 2: " + QString::number(can1Baud));
|
swcanListenOnly = true;
|
||||||
buffer[0] = (char)0xF1; //start of a command over serial
|
}
|
||||||
buffer[1] = 5; //setup canbus
|
else swcanListenOnly = false;
|
||||||
buffer[2] = (unsigned char)(can0Baud & 0xFF); //four bytes of ID LSB first
|
|
||||||
buffer[3] = (unsigned char)(can0Baud >> 8);
|
}
|
||||||
buffer[4] = (unsigned char)(can0Baud >> 16);
|
|
||||||
buffer[5] = (unsigned char)(can0Baud >> 24);
|
if (pBusIdx < 2) {
|
||||||
buffer[6] = (unsigned char)(can1Baud & 0xFF); //four bytes of ID LSB first
|
/* update baud rates */
|
||||||
buffer[7] = (unsigned char)(can1Baud >> 8);
|
QByteArray buffer;
|
||||||
buffer[8] = (unsigned char)(can1Baud >> 16);
|
qDebug() << "Got signal to update bauds. 1: " << (can0Baud & 0xFFFFFFF) <<" 2: " << (can1Baud & 0xFFFFFFF);
|
||||||
buffer[9] = (unsigned char)(can1Baud >> 24);
|
debugOutput("Got signal to update bauds. 1: " + QString::number((can0Baud & 0xFFFFFFF)) + " 2: " + QString::number((can1Baud & 0xFFFFFFF)));
|
||||||
buffer[10] = 0;
|
buffer[0] = (char)0xF1; //start of a command over serial
|
||||||
if (serial == NULL) return;
|
buffer[1] = 5; //setup canbus
|
||||||
if (!serial->isOpen()) return;
|
buffer[2] = (unsigned char)(can0Baud & 0xFF); //four bytes of ID LSB first
|
||||||
serial->write(buffer);
|
buffer[3] = (unsigned char)(can0Baud >> 8);
|
||||||
|
buffer[4] = (unsigned char)(can0Baud >> 16);
|
||||||
|
buffer[5] = (unsigned char)(can0Baud >> 24);
|
||||||
|
buffer[6] = (unsigned char)(can1Baud & 0xFF); //four bytes of ID LSB first
|
||||||
|
buffer[7] = (unsigned char)(can1Baud >> 8);
|
||||||
|
buffer[8] = (unsigned char)(can1Baud >> 16);
|
||||||
|
buffer[9] = (unsigned char)(can1Baud >> 24);
|
||||||
|
buffer[10] = 0;
|
||||||
|
if (serial == NULL) return;
|
||||||
|
if (!serial->isOpen()) return;
|
||||||
|
serial->write(buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* update baud rates */
|
||||||
|
QByteArray buffer;
|
||||||
|
qDebug() << "Got signal to update extended bus speeds SWCAN: " << swcanBaud <<" LIN1: " << lin1Baud << " LIN2: " << lin2Baud;
|
||||||
|
debugOutput("Got signal to update extended bus speeds SWCAN: " + QString::number(swcanBaud) + " LIN1: " + QString::number(lin1Baud) + " LIN2: " + QString::number(lin2Baud));
|
||||||
|
buffer[0] = (char)0xF1; //start of a command over serial
|
||||||
|
buffer[1] = 14; //setup extended buses
|
||||||
|
buffer[2] = (unsigned char)(swcanBaud & 0xFF); //four bytes of ID LSB first
|
||||||
|
buffer[3] = (unsigned char)(swcanBaud >> 8);
|
||||||
|
buffer[4] = (unsigned char)(swcanBaud >> 16);
|
||||||
|
buffer[5] = (unsigned char)(swcanBaud >> 24);
|
||||||
|
buffer[6] = (unsigned char)(lin1Baud & 0xFF); //four bytes of ID LSB first
|
||||||
|
buffer[7] = (unsigned char)(lin1Baud >> 8);
|
||||||
|
buffer[8] = (unsigned char)(lin1Baud >> 16);
|
||||||
|
buffer[9] = (unsigned char)(lin1Baud >> 24);
|
||||||
|
buffer[10] = (unsigned char)(lin2Baud & 0xFF); //four bytes of ID LSB first
|
||||||
|
buffer[11] = (unsigned char)(lin2Baud >> 8);
|
||||||
|
buffer[12] = (unsigned char)(lin2Baud >> 16);
|
||||||
|
buffer[13] = (unsigned char)(lin2Baud >> 24);
|
||||||
|
buffer[14] = 0;
|
||||||
|
if (serial == NULL) return;
|
||||||
|
if (!serial->isOpen()) return;
|
||||||
|
serial->write(buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -232,6 +278,10 @@ void GVRetSerial::connectDevice()
|
|||||||
output.append((char)0xE7); //this puts the device into binary comm mode
|
output.append((char)0xE7); //this puts the device into binary comm mode
|
||||||
output.append((char)0xE7);
|
output.append((char)0xE7);
|
||||||
|
|
||||||
|
output.append((char)0xF1);
|
||||||
|
output.append((char)0x0C); //get number of actually implemented buses. Not implemented except on M2RET
|
||||||
|
mNumBuses = 2; //the proper number if C/12 is not implemented
|
||||||
|
|
||||||
output.append((char)0xF1); //signal we want to issue a command
|
output.append((char)0xF1); //signal we want to issue a command
|
||||||
output.append((char)0x06); //request canbus stats from the board
|
output.append((char)0x06); //request canbus stats from the board
|
||||||
|
|
||||||
@@ -249,15 +299,11 @@ void GVRetSerial::connectDevice()
|
|||||||
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)0x09); //comm validation command
|
|
||||||
|
|
||||||
output.append((char)0xF1); //and another command
|
output.append((char)0xF1); //and another command
|
||||||
output.append((char)0x01); //Time Sync - Not implemented until 333 but we can try
|
output.append((char)0x01); //Time Sync - Not implemented until 333 but we can try
|
||||||
|
|
||||||
output.append((char)0xF1);
|
output.append((char)0xF1); //yet another command
|
||||||
output.append((char)0x12); //get number of actually implemented buses. Not implemented except on M2RET
|
output.append((char)0x09); //comm validation command
|
||||||
mNumBuses = 2; //the proper number if 0x12 is not implemented
|
|
||||||
|
|
||||||
continuousTimeSync = true;
|
continuousTimeSync = true;
|
||||||
|
|
||||||
@@ -274,7 +320,10 @@ void GVRetSerial::connectDevice()
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setStatus(CANCon::CONNECTED);
|
setStatus(CANCon::CONNECTED);
|
||||||
emit status(getStatus());
|
CANConStatus stats;
|
||||||
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
emit status(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* connect reading event */
|
/* connect reading event */
|
||||||
@@ -336,6 +385,10 @@ void GVRetSerial::debugInput(QByteArray bytes) {
|
|||||||
|
|
||||||
void GVRetSerial::procRXChar(unsigned char c)
|
void GVRetSerial::procRXChar(unsigned char c)
|
||||||
{
|
{
|
||||||
|
CANConStatus stats;
|
||||||
|
int oldBuses;
|
||||||
|
QByteArray output;
|
||||||
|
|
||||||
switch (rx_state)
|
switch (rx_state)
|
||||||
{
|
{
|
||||||
case IDLE:
|
case IDLE:
|
||||||
@@ -380,6 +433,12 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
rx_state = GET_NUM_BUSES;
|
rx_state = GET_NUM_BUSES;
|
||||||
|
qDebug() << "Got num buses reply";
|
||||||
|
rx_step = 0;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
rx_state = GET_EXT_BUSES;
|
||||||
|
qDebug() << "Got extended buses info reply";
|
||||||
rx_step = 0;
|
rx_step = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -545,6 +604,12 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
qDebug() << "Baud 0 = " << can0Baud;
|
qDebug() << "Baud 0 = " << can0Baud;
|
||||||
qDebug() << "Baud 1 = " << can1Baud;
|
qDebug() << "Baud 1 = " << can1Baud;
|
||||||
|
mBusData[0].mBus.setSpeed(can0Baud);
|
||||||
|
mBusData[1].mBus.setSpeed(can1Baud);
|
||||||
|
mBusData[0].mBus.setEnabled(can0Enabled);
|
||||||
|
mBusData[1].mBus.setEnabled(can1Enabled);
|
||||||
|
mBusData[0].mConfigured = true;
|
||||||
|
mBusData[1].mConfigured = true;
|
||||||
|
|
||||||
can0Baud |= 0x80000000;
|
can0Baud |= 0x80000000;
|
||||||
if (can0Enabled) can0Baud |= 0x40000000;
|
if (can0Enabled) can0Baud |= 0x40000000;
|
||||||
@@ -556,7 +621,9 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
if (deviceSingleWireMode > 0) can1Baud |= 0x10000000;
|
if (deviceSingleWireMode > 0) can1Baud |= 0x10000000;
|
||||||
|
|
||||||
setStatus(CANCon::CONNECTED);
|
setStatus(CANCon::CONNECTED);
|
||||||
emit status(getStatus());
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
emit status(stats);
|
||||||
|
|
||||||
int can0Status = 0x78; //updating everything we can update
|
int can0Status = 0x78; //updating everything we can update
|
||||||
int can1Status = 0x78;
|
int can1Status = 0x78;
|
||||||
@@ -606,8 +673,89 @@ void GVRetSerial::procRXChar(unsigned char c)
|
|||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
break;
|
break;
|
||||||
case GET_NUM_BUSES:
|
case GET_NUM_BUSES:
|
||||||
|
oldBuses = mNumBuses;
|
||||||
mNumBuses = c;
|
mNumBuses = c;
|
||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
|
qDebug() << "Get number of buses = " << mNumBuses;
|
||||||
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
mBusData.resize(mNumBuses);
|
||||||
|
if (mNumBuses > oldBuses)
|
||||||
|
{
|
||||||
|
for (int i = oldBuses; i < mNumBuses; i++)
|
||||||
|
{
|
||||||
|
mBusData[i].mConfigured = true;
|
||||||
|
mBusData[i].mBus = mBusData[0].mBus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.append((char)0xF1); //start a new command
|
||||||
|
output.append((char)13); //get extended buses
|
||||||
|
serial->write(output);
|
||||||
|
|
||||||
|
emit status(stats);
|
||||||
|
break;
|
||||||
|
case GET_EXT_BUSES:
|
||||||
|
switch (rx_step)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
swcanEnabled = (c & 0xF);
|
||||||
|
swcanListenOnly = (c >> 4);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
swcanBaud = c;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
swcanBaud |= c << 8;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
swcanBaud |= c << 16;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
swcanBaud |= c << 24;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
lin1Enabled = (c & 0xF);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
lin1Baud = c;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
lin1Baud |= c << 8;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
lin1Baud |= c << 16;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
lin1Baud |= c << 24;
|
||||||
|
case 10:
|
||||||
|
lin2Enabled = (c & 0xF);
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
lin2Baud = c;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
lin2Baud |= c << 8;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
lin2Baud |= c << 16;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
lin2Baud |= c << 24;
|
||||||
|
rx_state = IDLE;
|
||||||
|
qDebug() << "SWCAN Baud = " << swcanBaud;
|
||||||
|
qDebug() << "LIN1 Baud = " << lin1Baud;
|
||||||
|
qDebug() << "LIN2 Baud = " << lin2Baud;
|
||||||
|
mBusData[2].mBus.setSpeed(swcanBaud);
|
||||||
|
mBusData[2].mBus.setEnabled(swcanEnabled);
|
||||||
|
|
||||||
|
setStatus(CANCon::CONNECTED);
|
||||||
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
emit status(stats);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rx_step++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
namespace SERIALSTATE {
|
namespace SERIALSTATE {
|
||||||
|
|
||||||
enum STATE //keep this enum synchronized with the Arduino firmware project
|
enum STATE
|
||||||
{
|
{
|
||||||
IDLE,
|
IDLE,
|
||||||
GET_COMMAND,
|
GET_COMMAND,
|
||||||
@@ -29,12 +29,12 @@ enum STATE //keep this enum synchronized with the Arduino firmware project
|
|||||||
GET_CANBUS_PARAMS,
|
GET_CANBUS_PARAMS,
|
||||||
GET_DEVICE_INFO,
|
GET_DEVICE_INFO,
|
||||||
SET_SINGLEWIRE_MODE,
|
SET_SINGLEWIRE_MODE,
|
||||||
GET_NUM_BUSES
|
GET_NUM_BUSES,
|
||||||
|
GET_EXT_BUSES
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using namespace SERIALSTATE;
|
using namespace SERIALSTATE;
|
||||||
class GVRetSerial : public CANConnection
|
class GVRetSerial : public CANConnection
|
||||||
{
|
{
|
||||||
@@ -83,9 +83,9 @@ protected:
|
|||||||
STATE rx_state;
|
STATE rx_state;
|
||||||
uint32_t rx_step;
|
uint32_t rx_step;
|
||||||
CANFrame buildFrame;
|
CANFrame buildFrame;
|
||||||
int can0Baud, can1Baud;
|
int can0Baud, can1Baud, swcanBaud, lin1Baud, lin2Baud;
|
||||||
bool can0Enabled, can1Enabled;
|
bool can0Enabled, can1Enabled, swcanEnabled, lin1Enabled, lin2Enabled;
|
||||||
bool can0ListenOnly, can1ListenOnly;
|
bool can0ListenOnly, can1ListenOnly, swcanListenOnly;
|
||||||
int deviceBuildNum;
|
int deviceBuildNum;
|
||||||
int deviceSingleWireMode;
|
int deviceSingleWireMode;
|
||||||
uint32_t buildTimeBasis;
|
uint32_t buildTimeBasis;
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ void SocketCan::piStarted()
|
|||||||
mTimer.setInterval(1000);
|
mTimer.setInterval(1000);
|
||||||
mTimer.setSingleShot(false); //keep ticking
|
mTimer.setSingleShot(false); //keep ticking
|
||||||
mTimer.start();
|
mTimer.start();
|
||||||
|
mBusData[0].mBus.setEnabled(true);
|
||||||
|
mBusData[0].mConfigured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,6 +61,7 @@ bool SocketCan::piGetBusSettings(int pBusIdx, CANBus& pBus)
|
|||||||
|
|
||||||
void SocketCan::piSetBusSettings(int pBusIdx, CANBus bus)
|
void SocketCan::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||||
{
|
{
|
||||||
|
CANConStatus stats;
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if(0 != pBusIdx)
|
if(0 != pBusIdx)
|
||||||
return;
|
return;
|
||||||
@@ -109,7 +112,6 @@ bool SocketCan::piSendFrame(const CANFrame& pFrame)
|
|||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if(0 != pFrame.bus || pFrame.len>8)
|
if(0 != pFrame.bus || pFrame.len>8)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!mDev_p) return false;
|
if (!mDev_p) return false;
|
||||||
|
|
||||||
/* fill frame */
|
/* fill frame */
|
||||||
@@ -211,6 +213,7 @@ void SocketCan::framesReceived()
|
|||||||
|
|
||||||
void SocketCan::testConnection() {
|
void SocketCan::testConnection() {
|
||||||
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
||||||
|
CANConStatus stats;
|
||||||
|
|
||||||
switch(getStatus())
|
switch(getStatus())
|
||||||
{
|
{
|
||||||
@@ -220,7 +223,9 @@ void SocketCan::testConnection() {
|
|||||||
disconnectDevice();
|
disconnectDevice();
|
||||||
|
|
||||||
setStatus(CANCon::NOT_CONNECTED);
|
setStatus(CANCon::NOT_CONNECTED);
|
||||||
emit status(getStatus());
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
emit status(stats);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CANCon::NOT_CONNECTED:
|
case CANCon::NOT_CONNECTED:
|
||||||
@@ -229,13 +234,18 @@ void SocketCan::testConnection() {
|
|||||||
/* try to reconnect */
|
/* try to reconnect */
|
||||||
CANBus bus;
|
CANBus bus;
|
||||||
if(getBusConfig(0, bus))
|
if(getBusConfig(0, bus))
|
||||||
|
{
|
||||||
|
bus.setEnabled(true);
|
||||||
setBusSettings(0, bus);
|
setBusSettings(0, bus);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* disconnect test instance */
|
/* disconnect test instance */
|
||||||
dev_p->disconnectDevice();
|
dev_p->disconnectDevice();
|
||||||
|
|
||||||
setStatus(CANCon::CONNECTED);
|
setStatus(CANCon::CONNECTED);
|
||||||
emit status(getStatus());
|
stats.conStatus = getStatus();
|
||||||
|
stats.numHardwareBuses = mNumBuses;
|
||||||
|
emit status(stats);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: {}
|
default: {}
|
||||||
|
|||||||
@@ -0,0 +1,399 @@
|
|||||||
|
#include "frameplaybackobject.h"
|
||||||
|
|
||||||
|
FramePlaybackObject::FramePlaybackObject()
|
||||||
|
{
|
||||||
|
mThread_p = new QThread();
|
||||||
|
|
||||||
|
currentPosition = 0;
|
||||||
|
playbackInterval = 1;
|
||||||
|
playbackBurst = 1;
|
||||||
|
statusCounter = 0;
|
||||||
|
numBuses = 0;
|
||||||
|
playbackActive = false;
|
||||||
|
playbackForward = true;
|
||||||
|
useOrigTiming = false;
|
||||||
|
whichBusSend = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FramePlaybackObject::~FramePlaybackObject()
|
||||||
|
{
|
||||||
|
mThread_p->quit();
|
||||||
|
mThread_p->wait();
|
||||||
|
delete mThread_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 FramePlaybackObject::updatePosition(bool forward)
|
||||||
|
{
|
||||||
|
//qDebug() << "updatePosition";
|
||||||
|
if (forward)
|
||||||
|
{
|
||||||
|
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
||||||
|
else //hit the end of the current file
|
||||||
|
{
|
||||||
|
qDebug() << "hit end of current sequence";
|
||||||
|
currentSeqItem->currentLoopCount++;
|
||||||
|
currentPosition = 0;
|
||||||
|
if (currentSeqItem->currentLoopCount == currentSeqItem->maxLoops) //have we looped enough times?
|
||||||
|
{
|
||||||
|
playbackActive = false;
|
||||||
|
playbackTimer->stop();
|
||||||
|
emit EndOfFrameCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentPosition > 0) currentPosition--;
|
||||||
|
else //hit the beginning of the current sequence
|
||||||
|
{
|
||||||
|
qDebug() << "hit start of current sequence";
|
||||||
|
currentSeqItem->currentLoopCount++;
|
||||||
|
currentPosition = currentSeqItem->data.count() - 1;
|
||||||
|
if (currentSeqItem->currentLoopCount == currentSeqItem->maxLoops) //have we looped enough times?
|
||||||
|
{
|
||||||
|
playbackActive = false;
|
||||||
|
playbackTimer->stop();
|
||||||
|
emit EndOfFrameCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//only send frame out if its ID is checked in the list. Otherwise discard it.
|
||||||
|
CANFrame *thisFrame = ¤tSeqItem->data[currentPosition];
|
||||||
|
uint32_t originalBus = thisFrame->bus;
|
||||||
|
if (currentSeqItem->idFilters.find(thisFrame->ID).value())
|
||||||
|
{
|
||||||
|
if (whichBusSend > -1)
|
||||||
|
{
|
||||||
|
thisFrame->bus = whichBusSend;
|
||||||
|
sendingBuffer.append(*thisFrame);
|
||||||
|
}
|
||||||
|
else if (whichBusSend == -1)
|
||||||
|
{
|
||||||
|
for (int c = 0; c < numBuses; c++)
|
||||||
|
{
|
||||||
|
thisFrame->bus = c;
|
||||||
|
sendingBuffer.append(*thisFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //from file so retain original bus and send as-is
|
||||||
|
{
|
||||||
|
sendingBuffer.append(*thisFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
thisFrame->bus = originalBus;
|
||||||
|
}
|
||||||
|
return thisFrame->timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 FramePlaybackObject::peekPosition(bool forward)
|
||||||
|
{
|
||||||
|
int peekCurrentPosition = currentPosition;
|
||||||
|
if (forward)
|
||||||
|
{
|
||||||
|
if (peekCurrentPosition < (currentSeqItem->data.count() - 1)) peekCurrentPosition++; //still in same file so keep going
|
||||||
|
else //hit the end of the current file
|
||||||
|
{
|
||||||
|
return 0xFFFFFFFFFFFFFFFFull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (peekCurrentPosition > 0) peekCurrentPosition--;
|
||||||
|
else //hit the beginning of the current sequence
|
||||||
|
{
|
||||||
|
return 0xFFFFFFFFFFFFFFFFull;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CANFrame *thisFrame = ¤tSeqItem->data[peekCurrentPosition];
|
||||||
|
return thisFrame->timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::piStart()
|
||||||
|
{
|
||||||
|
playbackTimer = new QTimer();
|
||||||
|
playbackTimer->setTimerType(Qt::PreciseTimer);
|
||||||
|
playbackTimer->setInterval(1);
|
||||||
|
|
||||||
|
currentPosition = 0;
|
||||||
|
playbackActive = false;
|
||||||
|
playbackForward = true;
|
||||||
|
whichBusSend = 0;
|
||||||
|
|
||||||
|
connect(playbackTimer, &QTimer::timeout, this, &FramePlaybackObject::timerTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::piStop()
|
||||||
|
{
|
||||||
|
playbackTimer->stop();
|
||||||
|
delete playbackTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::initialize()
|
||||||
|
{
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||||
|
{
|
||||||
|
/* move ourself to the thread */
|
||||||
|
moveToThread(mThread_p); /*TODO handle errors */
|
||||||
|
/* connect started() */
|
||||||
|
connect(mThread_p, SIGNAL(started()), this, SLOT(initialize()));
|
||||||
|
/* start the thread */
|
||||||
|
mThread_p->start(QThread::HighPriority);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set started flag */
|
||||||
|
//mStarted = true;
|
||||||
|
|
||||||
|
/* in multithread case, this will be called before entering thread event loop */
|
||||||
|
return piStart();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::finalize()
|
||||||
|
{
|
||||||
|
/* 1) execute in mThread_p context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) )
|
||||||
|
{
|
||||||
|
/* if thread is finished, it means we call this function for the second time so we can leave */
|
||||||
|
if( !mThread_p->isFinished() )
|
||||||
|
{
|
||||||
|
/* we need to call piStop() */
|
||||||
|
QMetaObject::invokeMethod(this, "finalize",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
/* 3) stop thread */
|
||||||
|
mThread_p->quit();
|
||||||
|
if(!mThread_p->wait()) {
|
||||||
|
qDebug() << "can't stop thread";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2) call piStop in mThread context */
|
||||||
|
return piStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::startPlaybackForward()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "startPlaybackForward",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playbackActive = true;
|
||||||
|
playbackForward = true;
|
||||||
|
|
||||||
|
if (useOrigTiming)
|
||||||
|
{
|
||||||
|
playbackTimer->setInterval(1);
|
||||||
|
playbackElapsed.start();
|
||||||
|
if (currentSeqItem->data[currentPosition].timestamp > 2000)
|
||||||
|
playbackLastTimeStamp = currentSeqItem->data[currentPosition].timestamp - 2000;
|
||||||
|
else playbackLastTimeStamp = 0;
|
||||||
|
}
|
||||||
|
playbackTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::startPlaybackBackward()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "startPlaybackBackward",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playbackActive = true;
|
||||||
|
playbackForward = false;
|
||||||
|
if (useOrigTiming)
|
||||||
|
{
|
||||||
|
playbackElapsed.start();
|
||||||
|
playbackTimer->setInterval(1);
|
||||||
|
playbackLastTimeStamp = currentSeqItem->data[currentPosition].timestamp + 2000;
|
||||||
|
}
|
||||||
|
playbackTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::stepPlaybackForward()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "stepPlaybackForward",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendingBuffer.clear();
|
||||||
|
playbackTimer->stop();
|
||||||
|
playbackActive = false;
|
||||||
|
updatePosition(true);
|
||||||
|
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::stepPlaybackBackward()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "stepPlaybackBackward",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendingBuffer.clear();
|
||||||
|
playbackTimer->stop(); //pushing this button halts automatic playback
|
||||||
|
playbackActive = false;
|
||||||
|
|
||||||
|
updatePosition(false);
|
||||||
|
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::stopPlayback()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "stopPlayback",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playbackTimer->stop(); //pushing this button halts automatic playback
|
||||||
|
playbackActive = false;
|
||||||
|
currentPosition = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::pausePlayback()
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "pausePlayback",
|
||||||
|
Qt::BlockingQueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
playbackActive = false;
|
||||||
|
playbackTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::setSequenceObject(SequenceItem *item)
|
||||||
|
{
|
||||||
|
currentSeqItem = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::setUseOriginalTiming(bool state)
|
||||||
|
{
|
||||||
|
useOrigTiming = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::setSendingBus(int bus)
|
||||||
|
{
|
||||||
|
whichBusSend = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::setPlaybackBurst(int burst)
|
||||||
|
{
|
||||||
|
playbackBurst = burst;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::setNumBuses(int buses)
|
||||||
|
{
|
||||||
|
numBuses = buses;
|
||||||
|
}
|
||||||
|
|
||||||
|
//any time you touch objects that live in a potentially different thread you must switch into that thread.
|
||||||
|
//So this function is a bit different than the rest of the simple setters for that reason.
|
||||||
|
void FramePlaybackObject::setPlaybackInterval(int interval)
|
||||||
|
{
|
||||||
|
/* make sure we execute in mThread context */
|
||||||
|
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||||
|
QMetaObject::invokeMethod(this, "setPlaybackInterval",
|
||||||
|
Qt::BlockingQueuedConnection,
|
||||||
|
Q_ARG(int , interval) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
playbackInterval = interval;
|
||||||
|
playbackTimer->setInterval(interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackObject::timerTriggered()
|
||||||
|
{
|
||||||
|
sendingBuffer.clear();
|
||||||
|
|
||||||
|
if (useOrigTiming)
|
||||||
|
{
|
||||||
|
//get elapsed microseconds since last tick (in case timer skips or is otherwise inaccurate, though there are no guarantees about elapsed timer either)
|
||||||
|
quint64 elapsed = playbackElapsed.nsecsElapsed() / 1000;
|
||||||
|
playbackElapsed.start();
|
||||||
|
if (playbackForward)
|
||||||
|
{
|
||||||
|
playbackLastTimeStamp += elapsed;
|
||||||
|
//qDebug() << playbackLastTimeStamp;
|
||||||
|
//qDebug() << "El: " << elapsed;
|
||||||
|
while (peekPosition(true) <= playbackLastTimeStamp)
|
||||||
|
{
|
||||||
|
updatePosition(true);
|
||||||
|
}
|
||||||
|
if (peekPosition(true) == 0xFFFFFFFFFFFFFFFFull)
|
||||||
|
{
|
||||||
|
updatePosition(true); //this'll go to the next log (if there is one)
|
||||||
|
if (currentSeqItem->data[currentPosition].timestamp > 1000)
|
||||||
|
playbackLastTimeStamp = currentSeqItem->data[currentPosition].timestamp - 1000;
|
||||||
|
else playbackLastTimeStamp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (playbackLastTimeStamp > elapsed)
|
||||||
|
playbackLastTimeStamp -= elapsed;
|
||||||
|
else playbackLastTimeStamp = 0;
|
||||||
|
while (peekPosition(false) >= playbackLastTimeStamp && peekPosition(false) != 0xFFFFFFFFFFFFFFFFull)
|
||||||
|
{
|
||||||
|
updatePosition(false);
|
||||||
|
}
|
||||||
|
if (peekPosition(false) == 0xFFFFFFFFFFFFFFFFull)
|
||||||
|
{
|
||||||
|
updatePosition(false); //this'll go to the next log (if there is one)
|
||||||
|
playbackLastTimeStamp = currentSeqItem->data[currentPosition].timestamp + 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCounter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int count = 0; count < playbackBurst; count++)
|
||||||
|
{
|
||||||
|
if (!playbackActive)
|
||||||
|
{
|
||||||
|
playbackTimer->stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (playbackForward)
|
||||||
|
{
|
||||||
|
updatePosition(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updatePosition(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCounter += playbackInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusCounter > 249)
|
||||||
|
{
|
||||||
|
statusCounter = 0;
|
||||||
|
emit statusUpdate(currentPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug() << "sb: " << sendingBuffer.count();
|
||||||
|
if (sendingBuffer.count() > 0) CANConManager::getInstance()->sendFrames(sendingBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
#ifndef FRAMEPLAYBACKOBJECT_H
|
||||||
|
#define FRAMEPLAYBACKOBJECT_H
|
||||||
|
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "can_structs.h"
|
||||||
|
#include "connections/canconmanager.h"
|
||||||
|
|
||||||
|
//one entry in the sequence of data to use
|
||||||
|
struct SequenceItem
|
||||||
|
{
|
||||||
|
QString filename;
|
||||||
|
QVector<CANFrame> data;
|
||||||
|
QHash<int, bool> idFilters;
|
||||||
|
int maxLoops;
|
||||||
|
int currentLoopCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
broken out functionality that used to be in frameplaybackwindow. That mixed code for Model/View/Controller into one giant
|
||||||
|
class. I wasn't too concerned about that but the problem is that all code within a GUI object runs in GUI context and that
|
||||||
|
is most certainly not a feature, especially if you have a multi-core CPU. This object lives in a separate thread from the GUI
|
||||||
|
and thus is better scheduled and doesn't block the GUI thread. Really all functionality in this program should be broken into
|
||||||
|
a separate thread from GUI if it is prone to running a long time and/or taking up a lot of CPU time (unless it really does
|
||||||
|
have to interface with the GUI in some way. All gui touching code must run on its thread).
|
||||||
|
*/
|
||||||
|
class FramePlaybackObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FramePlaybackObject();
|
||||||
|
~FramePlaybackObject();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/**
|
||||||
|
* @brief start the device. This calls piStarted
|
||||||
|
* @note starts the working thread if required (piStart is called in the working thread context)
|
||||||
|
*/
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stop the device. This calls piStop
|
||||||
|
* @note if a working thread is used, piStop is called before exiting the working thread
|
||||||
|
*/
|
||||||
|
void finalize();
|
||||||
|
|
||||||
|
void startPlaybackForward();
|
||||||
|
void startPlaybackBackward();
|
||||||
|
void stepPlaybackForward();
|
||||||
|
void stepPlaybackBackward();
|
||||||
|
void stopPlayback();
|
||||||
|
void pausePlayback();
|
||||||
|
|
||||||
|
void setSequenceObject(SequenceItem *item);
|
||||||
|
void setUseOriginalTiming(bool state);
|
||||||
|
void setSendingBus(int bus);
|
||||||
|
void setPlaybackInterval(int interval);
|
||||||
|
void setPlaybackBurst(int burst);
|
||||||
|
void setNumBuses(int buses);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void EndOfFrameCache(); //we hit the end/beginning of the frame cache (depending on direction of playback)
|
||||||
|
void statusUpdate(int frameNum);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void timerTriggered();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<CANFrame> sendingBuffer;
|
||||||
|
SequenceItem *currentSeqItem;
|
||||||
|
int currentPosition;
|
||||||
|
QTimer *playbackTimer;
|
||||||
|
QElapsedTimer playbackElapsed;
|
||||||
|
quint64 playbackLastTimeStamp;
|
||||||
|
int playbackInterval;
|
||||||
|
int playbackBurst;
|
||||||
|
int numBuses;
|
||||||
|
int statusCounter;
|
||||||
|
bool playbackActive;
|
||||||
|
bool playbackForward;
|
||||||
|
bool useOrigTiming;
|
||||||
|
int whichBusSend;
|
||||||
|
QThread* mThread_p;
|
||||||
|
|
||||||
|
quint64 updatePosition(bool forward);
|
||||||
|
quint64 peekPosition(bool forward);
|
||||||
|
/**
|
||||||
|
* @brief starts the device
|
||||||
|
*/
|
||||||
|
void piStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief stops the device
|
||||||
|
*/
|
||||||
|
void piStop();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FRAMEPLAYBACKOBJECT_H
|
||||||
+142
-174
@@ -32,47 +32,50 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, QWidge
|
|||||||
ui->comboCANBus->addItem(tr("From File"));
|
ui->comboCANBus->addItem(tr("From File"));
|
||||||
ui->comboCANBus->setCurrentIndex(0);
|
ui->comboCANBus->setCurrentIndex(0);
|
||||||
|
|
||||||
|
playbackObject.initialize();
|
||||||
|
playbackObject.setNumBuses(numBuses);
|
||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
modelFrames = frames;
|
modelFrames = frames;
|
||||||
|
|
||||||
playbackTimer = new QTimer();
|
|
||||||
playbackTimer->setTimerType(Qt::PreciseTimer);
|
|
||||||
|
|
||||||
currentPosition = 0;
|
|
||||||
playbackActive = false;
|
|
||||||
playbackForward = true;
|
|
||||||
whichBusSend = 0; //0 = no bus, 1 = bus 0, 2 = bus 1, 4 = from file - Bitfield so you can 'or' them.
|
|
||||||
currentSeqItem = NULL;
|
currentSeqItem = NULL;
|
||||||
currentSeqNum = -1;
|
currentSeqNum = -1;
|
||||||
|
currentPosition = 0;
|
||||||
|
forward = true;
|
||||||
|
isPlaying = false;
|
||||||
|
|
||||||
updateFrameLabel();
|
updateFrameLabel();
|
||||||
|
|
||||||
connect(ui->btnStepBack, SIGNAL(clicked(bool)), this, SLOT(btnBackOneClick()));
|
connect(ui->btnStepBack, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnBackOneClick);
|
||||||
connect(ui->btnPause, SIGNAL(clicked(bool)), this, SLOT(btnPauseClick()));
|
connect(ui->btnPause, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnPauseClick);
|
||||||
connect(ui->btnPlayReverse, SIGNAL(clicked(bool)), this, SLOT(btnReverseClick()));
|
connect(ui->btnPlayReverse, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnReverseClick);
|
||||||
connect(ui->btnStop, SIGNAL(clicked(bool)), this, SLOT(btnStopClick()));
|
connect(ui->btnStop, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnStopClick);
|
||||||
connect(ui->btnPlay, SIGNAL(clicked(bool)), this, SLOT(btnPlayClick()));
|
connect(ui->btnPlay, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnPlayClick);
|
||||||
connect(ui->btnStepForward, SIGNAL(clicked(bool)), this, SLOT(btnFwdOneClick()));
|
connect(ui->btnStepForward, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnFwdOneClick);
|
||||||
connect(ui->btnSelectAll, SIGNAL(clicked(bool)), this, SLOT(btnSelectAllClick()));
|
connect(ui->btnSelectAll, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnSelectAllClick);
|
||||||
connect(ui->btnSelectNone, SIGNAL(clicked(bool)), this, SLOT(btnSelectNoneClick()));
|
connect(ui->btnSelectNone, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnSelectNoneClick);
|
||||||
connect(ui->btnDelete, SIGNAL(clicked(bool)), this, SLOT(btnDeleteCurrSeq()));
|
connect(ui->btnDelete, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnDeleteCurrSeq);
|
||||||
connect(ui->spinPlaySpeed, SIGNAL(valueChanged(int)), this, SLOT(changePlaybackSpeed(int)));
|
connect(ui->spinPlaySpeed, SIGNAL(valueChanged(int)), this, SLOT(changePlaybackSpeed(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, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(changeIDFiltering(QListWidgetItem*)));
|
connect(ui->listID, &QListWidget::itemClicked, this, &FramePlaybackWindow::changeIDFiltering);
|
||||||
connect(playbackTimer, SIGNAL(timeout()), this, SLOT(timerTriggered()));
|
connect(ui->btnLoadFile, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadFile);
|
||||||
connect(ui->btnLoadFile, SIGNAL(clicked(bool)), this, SLOT(btnLoadFile()));
|
connect(ui->btnLoadLive, &QAbstractButton::clicked, this, &FramePlaybackWindow::btnLoadLive);
|
||||||
connect(ui->btnLoadLive, SIGNAL(clicked(bool)), this, SLOT(btnLoadLive()));
|
connect(ui->tblSequence, &QTableWidget::cellPressed, this, &FramePlaybackWindow::seqTableCellClicked);
|
||||||
connect(ui->tblSequence, SIGNAL(cellPressed(int,int)), this, SLOT(seqTableCellClicked(int,int)));
|
connect(ui->tblSequence, &QTableWidget::cellChanged, this, &FramePlaybackWindow::seqTableCellChanged);
|
||||||
connect(ui->tblSequence, SIGNAL(cellChanged(int,int)), this, SLOT(seqTableCellChanged(int,int)));
|
connect(ui->btnLoadFilters, &QAbstractButton::clicked, this, &FramePlaybackWindow::loadFilters);
|
||||||
connect(ui->btnLoadFilters, SIGNAL(clicked(bool)), this, SLOT(loadFilters()));
|
connect(ui->btnSaveFilters, &QAbstractButton::clicked, this, &FramePlaybackWindow::saveFilters);
|
||||||
connect(ui->btnSaveFilters, SIGNAL(clicked(bool)), this, SLOT(saveFilters()));
|
connect(ui->cbOriginalTiming, &QCheckBox::toggled, this, &FramePlaybackWindow::useOrigTimingClicked);
|
||||||
|
|
||||||
|
connect(&playbackObject, &FramePlaybackObject::EndOfFrameCache, this, &FramePlaybackWindow::EndOfFrameCache);
|
||||||
|
connect(&playbackObject, &FramePlaybackObject::statusUpdate, this, &FramePlaybackWindow::getStatusUpdate);
|
||||||
|
|
||||||
ui->listID->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->listID->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(ui->listID, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuFilters(QPoint)));
|
connect(ui->listID, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuFilters(QPoint)));
|
||||||
|
|
||||||
playbackTimer->setInterval(ui->spinPlaySpeed->value()); //set the timer to the default value of the control
|
playbackObject.setPlaybackInterval(ui->spinPlaySpeed->value());
|
||||||
|
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << "Source" << "Loops";
|
headers << "Source" << "Loops";
|
||||||
@@ -85,9 +88,6 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, QWidge
|
|||||||
FramePlaybackWindow::~FramePlaybackWindow()
|
FramePlaybackWindow::~FramePlaybackWindow()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
|
|
||||||
playbackTimer->stop();
|
|
||||||
delete playbackTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::showEvent(QShowEvent *)
|
void FramePlaybackWindow::showEvent(QShowEvent *)
|
||||||
@@ -115,7 +115,8 @@ void FramePlaybackWindow::readSettings()
|
|||||||
}
|
}
|
||||||
ui->spinPlaySpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
|
ui->spinPlaySpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
|
||||||
ui->comboCANBus->setCurrentIndex(settings.value("Playback/SendingBus", 0).toInt());
|
ui->comboCANBus->setCurrentIndex(settings.value("Playback/SendingBus", 0).toInt());
|
||||||
whichBusSend = ui->comboCANBus->currentIndex();
|
|
||||||
|
calculateWhichBus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::writeSettings()
|
void FramePlaybackWindow::writeSettings()
|
||||||
@@ -256,6 +257,73 @@ void FramePlaybackWindow::refreshIDList()
|
|||||||
ui->listID->sortItems();
|
ui->listID->sortItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramePlaybackWindow::calculateWhichBus()
|
||||||
|
{
|
||||||
|
int idx = ui->comboCANBus->currentIndex();
|
||||||
|
int maxIdx = ui->comboCANBus->count() - 1;
|
||||||
|
int out = idx;
|
||||||
|
if (idx == (maxIdx - 1) ) out = -1;
|
||||||
|
if (idx == maxIdx) out = -2;
|
||||||
|
|
||||||
|
playbackObject.setSendingBus(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackWindow::EndOfFrameCache()
|
||||||
|
{
|
||||||
|
if (forward)
|
||||||
|
{
|
||||||
|
currentSeqNum++; //go forward in the sequence
|
||||||
|
if (currentSeqNum == seqItems.count()) //are we at the end of the sequence?
|
||||||
|
{
|
||||||
|
//reset the loop figures for each sequence entry
|
||||||
|
for (int i = 0; i < seqItems.count(); i++) seqItems[i].currentLoopCount = 0;
|
||||||
|
currentSeqNum = 0;
|
||||||
|
if (ui->cbLoop->isChecked()) //go back to beginning if we're looping the sequence
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else //not looping so stop playback entirely
|
||||||
|
{
|
||||||
|
isPlaying = false;
|
||||||
|
playbackObject.stopPlayback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentSeqItem = &seqItems[currentSeqNum];
|
||||||
|
playbackObject.setSequenceObject(currentSeqItem);
|
||||||
|
if (isPlaying) playbackObject.startPlaybackForward();
|
||||||
|
ui->tblSequence->setCurrentCell(currentSeqNum, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentSeqNum--; //go backward in the sequence
|
||||||
|
if (currentSeqNum == -1) //are we trying to go past the beginning?
|
||||||
|
{
|
||||||
|
//reset the loop figures for each sequence entry
|
||||||
|
for (int i = 0; i < seqItems.count(); i++) seqItems[i].currentLoopCount = 0;
|
||||||
|
currentSeqNum = seqItems.count() - 1;
|
||||||
|
if (ui->cbLoop->isChecked()) //go back to the last sequence entry if we're looping
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else //not looping so stop playback entirely
|
||||||
|
{
|
||||||
|
isPlaying = false;
|
||||||
|
playbackObject.stopPlayback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentSeqItem = &seqItems[currentSeqNum];
|
||||||
|
playbackObject.setSequenceObject(currentSeqItem);
|
||||||
|
if (isPlaying) playbackObject.startPlaybackBackward();
|
||||||
|
ui->tblSequence->setCurrentCell(currentSeqNum, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackWindow::getStatusUpdate(int frameNum)
|
||||||
|
{
|
||||||
|
currentPosition = frameNum;
|
||||||
|
updateFrameLabel();
|
||||||
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::updateFrameLabel()
|
void FramePlaybackWindow::updateFrameLabel()
|
||||||
{
|
{
|
||||||
int row = currentSeqNum;
|
int row = currentSeqNum;
|
||||||
@@ -313,15 +381,27 @@ void FramePlaybackWindow::fillIDHash(SequenceItem &item)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FramePlaybackWindow::useOrigTimingClicked()
|
||||||
|
{
|
||||||
|
if (ui->cbOriginalTiming->isChecked())
|
||||||
|
{
|
||||||
|
ui->spinBurstSpeed->setEnabled(false);
|
||||||
|
ui->spinPlaySpeed->setEnabled(false);
|
||||||
|
playbackObject.setUseOriginalTiming(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->spinBurstSpeed->setEnabled(true);
|
||||||
|
ui->spinPlaySpeed->setEnabled(true);
|
||||||
|
playbackObject.setUseOriginalTiming(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnDeleteCurrSeq()
|
void FramePlaybackWindow::btnDeleteCurrSeq()
|
||||||
{
|
{
|
||||||
if (currentSeqNum == -1) return;
|
if (currentSeqNum == -1) return;
|
||||||
|
|
||||||
if (playbackActive)
|
playbackObject.stopPlayback();
|
||||||
{
|
|
||||||
playbackActive = false;
|
|
||||||
playbackTimer->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
seqItems.removeAt(currentSeqNum);
|
seqItems.removeAt(currentSeqNum);
|
||||||
ui->tblSequence->removeRow(currentSeqNum);
|
ui->tblSequence->removeRow(currentSeqNum);
|
||||||
@@ -345,6 +425,7 @@ void FramePlaybackWindow::btnLoadFile()
|
|||||||
|
|
||||||
if (FrameFileIO::loadFrameFile(filename, &item.data))
|
if (FrameFileIO::loadFrameFile(filename, &item.data))
|
||||||
{
|
{
|
||||||
|
qSort(item.data); //sort by timestamp to be sure it's in order
|
||||||
QStringList fileList = filename.split('/');
|
QStringList fileList = filename.split('/');
|
||||||
item.filename = fileList[fileList.length() - 1];
|
item.filename = fileList[fileList.length() - 1];
|
||||||
item.currentLoopCount = 0;
|
item.currentLoopCount = 0;
|
||||||
@@ -364,6 +445,7 @@ void FramePlaybackWindow::btnLoadFile()
|
|||||||
{
|
{
|
||||||
currentSeqNum = 0;
|
currentSeqNum = 0;
|
||||||
currentSeqItem = &seqItems[0];
|
currentSeqItem = &seqItems[0];
|
||||||
|
playbackObject.setSequenceObject(currentSeqItem);
|
||||||
}
|
}
|
||||||
refreshIDList();
|
refreshIDList();
|
||||||
updateFrameLabel();
|
updateFrameLabel();
|
||||||
@@ -377,6 +459,7 @@ void FramePlaybackWindow::btnLoadLive()
|
|||||||
item.currentLoopCount = 0;
|
item.currentLoopCount = 0;
|
||||||
item.maxLoops = 1;
|
item.maxLoops = 1;
|
||||||
item.data = QVector<CANFrame>(*modelFrames); //create a copy of the current frames from the main view
|
item.data = QVector<CANFrame>(*modelFrames); //create a copy of the current frames from the main view
|
||||||
|
qSort(item.data); //be sure it's all in time based order
|
||||||
fillIDHash(item);
|
fillIDHash(item);
|
||||||
if (ui->tblSequence->currentRow() == -1)
|
if (ui->tblSequence->currentRow() == -1)
|
||||||
{
|
{
|
||||||
@@ -391,6 +474,7 @@ void FramePlaybackWindow::btnLoadLive()
|
|||||||
{
|
{
|
||||||
currentSeqNum = 0;
|
currentSeqNum = 0;
|
||||||
currentSeqItem = &seqItems[0];
|
currentSeqItem = &seqItems[0];
|
||||||
|
playbackObject.setSequenceObject(currentSeqItem);
|
||||||
}
|
}
|
||||||
refreshIDList();
|
refreshIDList();
|
||||||
updateFrameLabel();
|
updateFrameLabel();
|
||||||
@@ -399,32 +483,28 @@ void FramePlaybackWindow::btnLoadLive()
|
|||||||
|
|
||||||
void FramePlaybackWindow::btnBackOneClick()
|
void FramePlaybackWindow::btnBackOneClick()
|
||||||
{
|
{
|
||||||
sendingBuffer.clear();
|
forward = false;
|
||||||
playbackTimer->stop(); //pushing this button halts automatic playback
|
isPlaying = false;
|
||||||
playbackActive = false;
|
playbackObject.stepPlaybackBackward();
|
||||||
|
|
||||||
updatePosition(false);
|
|
||||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnPauseClick()
|
void FramePlaybackWindow::btnPauseClick()
|
||||||
{
|
{
|
||||||
playbackActive = false;
|
isPlaying = false;
|
||||||
playbackTimer->stop();
|
playbackObject.pausePlayback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnReverseClick()
|
void FramePlaybackWindow::btnReverseClick()
|
||||||
{
|
{
|
||||||
playbackActive = true;
|
forward = false;
|
||||||
playbackForward = false;
|
isPlaying = true;
|
||||||
playbackTimer->start();
|
playbackObject.startPlaybackBackward();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnStopClick()
|
void FramePlaybackWindow::btnStopClick()
|
||||||
{
|
{
|
||||||
playbackTimer->stop(); //pushing this button halts automatic playback
|
isPlaying = false;
|
||||||
playbackActive = false;
|
playbackObject.stopPlayback();
|
||||||
currentPosition = 0;
|
|
||||||
if (seqItems.count() > 0)
|
if (seqItems.count() > 0)
|
||||||
{
|
{
|
||||||
currentSeqNum = 0;
|
currentSeqNum = 0;
|
||||||
@@ -438,29 +518,32 @@ void FramePlaybackWindow::btnStopClick()
|
|||||||
{
|
{
|
||||||
ui->tblSequence->setCurrentCell(0, 0);
|
ui->tblSequence->setCurrentCell(0, 0);
|
||||||
refreshIDList();
|
refreshIDList();
|
||||||
}
|
}
|
||||||
updateFrameLabel();
|
updateFrameLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnPlayClick()
|
void FramePlaybackWindow::btnPlayClick()
|
||||||
{
|
{
|
||||||
playbackActive = true;
|
forward = true;
|
||||||
playbackForward = true;
|
isPlaying = true;
|
||||||
playbackTimer->start();
|
playbackObject.startPlaybackForward();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::btnFwdOneClick()
|
void FramePlaybackWindow::btnFwdOneClick()
|
||||||
{
|
{
|
||||||
sendingBuffer.clear();
|
forward = true;
|
||||||
playbackTimer->stop();
|
isPlaying = false;
|
||||||
playbackActive = false;
|
playbackObject.stepPlaybackForward();
|
||||||
updatePosition(true);
|
|
||||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::changePlaybackSpeed(int newSpeed)
|
void FramePlaybackWindow::changePlaybackSpeed(int newSpeed)
|
||||||
{
|
{
|
||||||
playbackTimer->setInterval(newSpeed);
|
playbackObject.setPlaybackInterval(newSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramePlaybackWindow::changeBurstRate(int burst)
|
||||||
|
{
|
||||||
|
playbackObject.setPlaybackBurst(burst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::changeLooping(bool check)
|
void FramePlaybackWindow::changeLooping(bool check)
|
||||||
@@ -470,7 +553,7 @@ void FramePlaybackWindow::changeLooping(bool check)
|
|||||||
|
|
||||||
void FramePlaybackWindow::changeSendingBus(int newIdx)
|
void FramePlaybackWindow::changeSendingBus(int newIdx)
|
||||||
{
|
{
|
||||||
whichBusSend = newIdx;
|
calculateWhichBus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item)
|
void FramePlaybackWindow::changeIDFiltering(QListWidgetItem *item)
|
||||||
@@ -499,118 +582,3 @@ void FramePlaybackWindow::btnSelectNoneClick()
|
|||||||
currentSeqItem->idFilters[Utility::ParseStringToNum(item->text())] = false;
|
currentSeqItem->idFilters[Utility::ParseStringToNum(item->text())] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramePlaybackWindow::timerTriggered()
|
|
||||||
{
|
|
||||||
sendingBuffer.clear();
|
|
||||||
for (int count = 0; count < ui->spinBurstSpeed->value(); count++)
|
|
||||||
{
|
|
||||||
if (!playbackActive)
|
|
||||||
{
|
|
||||||
playbackTimer->stop();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (playbackForward)
|
|
||||||
{
|
|
||||||
updatePosition(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updatePosition(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CANConManager::getInstance()->sendFrames(sendingBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FramePlaybackWindow::updatePosition(bool forward)
|
|
||||||
{
|
|
||||||
//qDebug() << "updatePosition";
|
|
||||||
if (forward)
|
|
||||||
{
|
|
||||||
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
|
||||||
else //hit the end of the current file
|
|
||||||
{
|
|
||||||
qDebug() << "hit end of current sequence";
|
|
||||||
currentSeqItem->currentLoopCount++;
|
|
||||||
currentPosition = 0;
|
|
||||||
if (currentSeqItem->currentLoopCount == currentSeqItem->maxLoops) //have we looped enough times?
|
|
||||||
{
|
|
||||||
currentSeqNum++; //go forward in the sequence
|
|
||||||
if (currentSeqNum == seqItems.count()) //are we at the end of the sequence?
|
|
||||||
{
|
|
||||||
//reset the loop figures for each sequence entry
|
|
||||||
for (int i = 0; i < seqItems.count(); i++) seqItems[i].currentLoopCount = 0;
|
|
||||||
currentSeqNum = 0;
|
|
||||||
if (ui->cbLoop->isChecked()) //go back to beginning if we're looping the sequence
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else //not looping so stop playback entirely
|
|
||||||
{
|
|
||||||
playbackActive = false;
|
|
||||||
playbackTimer->stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentSeqItem = &seqItems[currentSeqNum];
|
|
||||||
ui->tblSequence->setCurrentCell(currentSeqNum, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (currentPosition > 0) currentPosition--;
|
|
||||||
else //hit the beginning of the current sequence
|
|
||||||
{
|
|
||||||
qDebug() << "hit start of current sequence";
|
|
||||||
currentSeqItem->currentLoopCount++;
|
|
||||||
currentPosition = currentSeqItem->data.count() - 1;
|
|
||||||
if (currentSeqItem->currentLoopCount == currentSeqItem->maxLoops) //have we looped enough times?
|
|
||||||
{
|
|
||||||
currentSeqNum--; //go backward in the sequence
|
|
||||||
if (currentSeqNum == -1) //are we trying to go past the beginning?
|
|
||||||
{
|
|
||||||
//reset the loop figures for each sequence entry
|
|
||||||
for (int i = 0; i < seqItems.count(); i++) seqItems[i].currentLoopCount = 0;
|
|
||||||
currentSeqNum = seqItems.count() - 1;
|
|
||||||
if (ui->cbLoop->isChecked()) //go back to the last sequence entry if we're looping
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
else //not looping so stop playback entirely
|
|
||||||
{
|
|
||||||
playbackActive = false;
|
|
||||||
playbackTimer->stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentSeqItem = &seqItems[currentSeqNum];
|
|
||||||
ui->tblSequence->setCurrentCell(currentSeqNum, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateFrameLabel();
|
|
||||||
//only send frame out if its ID is checked in the list. Otherwise discard it.
|
|
||||||
CANFrame *thisFrame = ¤tSeqItem->data[currentPosition];
|
|
||||||
uint32_t originalBus = thisFrame->bus;
|
|
||||||
if (currentSeqItem->idFilters.find(thisFrame->ID).value())
|
|
||||||
{
|
|
||||||
if (whichBusSend < ui->comboCANBus->count() - 2)
|
|
||||||
{
|
|
||||||
thisFrame->bus = whichBusSend;
|
|
||||||
sendingBuffer.append(*thisFrame);
|
|
||||||
}
|
|
||||||
else if (whichBusSend == (ui->comboCANBus->count() - 2)) //all
|
|
||||||
{
|
|
||||||
for (int c = 0; c < ui->comboCANBus->count() - 2; c++)
|
|
||||||
{
|
|
||||||
thisFrame->bus = c;
|
|
||||||
sendingBuffer.append(*thisFrame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //from file so retain original bus and send as-is
|
|
||||||
{
|
|
||||||
sendingBuffer.append(*thisFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
thisFrame->bus = originalBus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+11
-20
@@ -3,24 +3,14 @@
|
|||||||
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QTimer>
|
|
||||||
#include "can_structs.h"
|
#include "can_structs.h"
|
||||||
#include "framefileio.h"
|
#include "framefileio.h"
|
||||||
|
#include "frameplaybackobject.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FramePlaybackWindow;
|
class FramePlaybackWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
//one entry in the sequence of data to use
|
|
||||||
struct SequenceItem
|
|
||||||
{
|
|
||||||
QString filename;
|
|
||||||
QVector<CANFrame> data;
|
|
||||||
QHash<int, bool> idFilters;
|
|
||||||
int maxLoops;
|
|
||||||
int currentLoopCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FramePlaybackWindow : public QDialog
|
class FramePlaybackWindow : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -38,12 +28,12 @@ private slots:
|
|||||||
void btnFwdOneClick();
|
void btnFwdOneClick();
|
||||||
void btnDeleteCurrSeq();
|
void btnDeleteCurrSeq();
|
||||||
void changePlaybackSpeed(int newSpeed);
|
void changePlaybackSpeed(int newSpeed);
|
||||||
|
void changeBurstRate(int burst);
|
||||||
void changeLooping(bool check);
|
void changeLooping(bool check);
|
||||||
void changeSendingBus(int newIdx);
|
void changeSendingBus(int newIdx);
|
||||||
void changeIDFiltering(QListWidgetItem *item);
|
void changeIDFiltering(QListWidgetItem *item);
|
||||||
void btnSelectAllClick();
|
void btnSelectAllClick();
|
||||||
void btnSelectNoneClick();
|
void btnSelectNoneClick();
|
||||||
void timerTriggered();
|
|
||||||
void btnLoadFile();
|
void btnLoadFile();
|
||||||
void btnLoadLive();
|
void btnLoadLive();
|
||||||
void seqTableCellClicked(int row, int col);
|
void seqTableCellClicked(int row, int col);
|
||||||
@@ -51,30 +41,31 @@ private slots:
|
|||||||
void contextMenuFilters(QPoint);
|
void contextMenuFilters(QPoint);
|
||||||
void saveFilters();
|
void saveFilters();
|
||||||
void loadFilters();
|
void loadFilters();
|
||||||
|
void useOrigTimingClicked();
|
||||||
|
void getStatusUpdate(int frameNum);
|
||||||
|
void EndOfFrameCache();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FramePlaybackWindow *ui;
|
Ui::FramePlaybackWindow *ui;
|
||||||
QList<int> foundID;
|
QList<int> foundID;
|
||||||
QList<CANFrame> frameCache;
|
QList<CANFrame> frameCache;
|
||||||
QList<CANFrame> sendingBuffer;
|
|
||||||
const QVector<CANFrame> *modelFrames;
|
const QVector<CANFrame> *modelFrames;
|
||||||
int currentPosition;
|
|
||||||
QTimer *playbackTimer;
|
|
||||||
bool playbackActive;
|
|
||||||
bool playbackForward;
|
|
||||||
int whichBusSend;
|
|
||||||
QList<SequenceItem> seqItems;
|
QList<SequenceItem> seqItems;
|
||||||
SequenceItem *currentSeqItem;
|
SequenceItem *currentSeqItem;
|
||||||
int currentSeqNum;
|
int currentSeqNum;
|
||||||
|
FramePlaybackObject playbackObject;
|
||||||
|
bool forward;
|
||||||
|
bool isPlaying;
|
||||||
|
int currentPosition;
|
||||||
|
|
||||||
void refreshIDList();
|
void refreshIDList();
|
||||||
void updateFrameLabel();
|
void updateFrameLabel();
|
||||||
void updatePosition(bool forward);
|
void fillIDHash(SequenceItem &item);
|
||||||
void fillIDHash(SequenceItem &item);
|
|
||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
void readSettings();
|
void readSettings();
|
||||||
void writeSettings();
|
void writeSettings();
|
||||||
|
void calculateWhichBus();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FRAMEPLAYBACKWINDOW_H
|
#endif // FRAMEPLAYBACKWINDOW_H
|
||||||
|
|||||||
+16
-70
@@ -25,6 +25,9 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="tableConnections">
|
<widget class="QTableView" name="tableConnections">
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="selectionMode">
|
<property name="selectionMode">
|
||||||
<enum>QAbstractItemView::SingleSelection</enum>
|
<enum>QAbstractItemView::SingleSelection</enum>
|
||||||
</property>
|
</property>
|
||||||
@@ -35,13 +38,6 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnNewConn">
|
|
||||||
<property name="text">
|
|
||||||
<string>New Connection</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnRemoveBus">
|
<widget class="QPushButton" name="btnRemoveBus">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -49,10 +45,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="btnActivateAll">
|
<widget class="QPushButton" name="btnActivateAll">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -193,45 +185,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="ckSingleWire">
|
|
||||||
<property name="text">
|
|
||||||
<string>Single Wire Mode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="ckListenOnly">
|
|
||||||
<property name="text">
|
|
||||||
<string>Listen Only Mode</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="ckEnabled">
|
|
||||||
<property name="text">
|
|
||||||
<string>Enabled</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>CAN Speed</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="cbSpeed">
|
|
||||||
<property name="editable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
@@ -241,15 +194,21 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnRevert">
|
|
||||||
<property name="text">
|
|
||||||
<string>Revert</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignHCenter">
|
||||||
<widget class="QCheckBox" name="ckEnableConsole">
|
<widget class="QCheckBox" name="ckEnableConsole">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -319,19 +278,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@@ -100,6 +100,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="cbOriginalTiming">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use original frame timing from captured frames</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
Reference in New Issue
Block a user