+13
-5
@@ -4,7 +4,7 @@
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
QT += core gui serialbus
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport qml
|
||||
|
||||
@@ -50,8 +50,11 @@ SOURCES += main.cpp\
|
||||
isotp_interpreterwindow.cpp \
|
||||
isotp_handler.cpp \
|
||||
canconnectionmodel.cpp \
|
||||
canconnection.cpp \
|
||||
canconnectioncontainer.cpp
|
||||
canbus.cpp \
|
||||
connections/canconnection.cpp \
|
||||
connections/socketcan.cpp \
|
||||
connections/canconfactory.cpp \
|
||||
connections/gvretserial.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
can_structs.h \
|
||||
@@ -88,8 +91,13 @@ HEADERS += mainwindow.h \
|
||||
isotp_interpreterwindow.h \
|
||||
isotp_handler.h \
|
||||
canconnectionmodel.h \
|
||||
canconnection.h \
|
||||
canconnectioncontainer.h
|
||||
canbus.h \
|
||||
utils/lfqueue.h \
|
||||
connections/canconnection.h \
|
||||
connections/socketcan.h \
|
||||
connections/canconconst.h \
|
||||
connections/canconfactory.h \
|
||||
connections/gvretserial.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
graphingwindow.ui \
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#include <QVector>
|
||||
#include <stdint.h>
|
||||
|
||||
class CANFrame
|
||||
struct CANFrame
|
||||
{
|
||||
public:
|
||||
int ID;
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
#include <QObject>
|
||||
#include "canbus.h"
|
||||
|
||||
CANBus::CANBus()
|
||||
{
|
||||
speed = 250000;
|
||||
listenOnly = false;
|
||||
singleWire = false;
|
||||
active = false;
|
||||
}
|
||||
|
||||
|
||||
CANBus::CANBus(const CANBus& pBus) :
|
||||
speed(pBus.speed),
|
||||
listenOnly(pBus.listenOnly),
|
||||
singleWire(pBus.singleWire),
|
||||
active(pBus.active) {}
|
||||
|
||||
|
||||
bool CANBus::operator==(CANBus& bus) {
|
||||
return speed == bus.speed &&
|
||||
listenOnly == bus.listenOnly &&
|
||||
singleWire == bus.singleWire &&
|
||||
active == bus.active;
|
||||
}
|
||||
|
||||
|
||||
void CANBus::setSpeed(int newSpeed)
|
||||
{
|
||||
speed = newSpeed;
|
||||
}
|
||||
|
||||
void CANBus::setListenOnly(bool mode)
|
||||
{
|
||||
listenOnly = mode;
|
||||
}
|
||||
|
||||
void CANBus::setSingleWire(bool mode)
|
||||
{
|
||||
singleWire = mode;
|
||||
}
|
||||
|
||||
void CANBus::setEnabled(bool mode)
|
||||
{
|
||||
active = mode;
|
||||
}
|
||||
|
||||
int CANBus::getSpeed()
|
||||
{
|
||||
return speed;
|
||||
}
|
||||
|
||||
bool CANBus::isListenOnly()
|
||||
{
|
||||
return listenOnly;
|
||||
}
|
||||
|
||||
bool CANBus::isSingleWire()
|
||||
{
|
||||
return singleWire;
|
||||
}
|
||||
|
||||
bool CANBus::isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef CANBus_H
|
||||
#define CANBus_H
|
||||
|
||||
|
||||
class CANBus
|
||||
{
|
||||
public:
|
||||
CANBus();
|
||||
CANBus(const CANBus&);
|
||||
bool operator==(CANBus&);
|
||||
virtual ~CANBus(){}; /*TODO: remove connection from CANBus and add CANBus as an element of CANConnection */
|
||||
int speed;
|
||||
bool listenOnly;
|
||||
bool singleWire;
|
||||
bool active; //is this bus turned on?
|
||||
|
||||
|
||||
void setSpeed(int); // new speed
|
||||
void setListenOnly(bool); //bool for whether to only listen
|
||||
void setSingleWire(bool); //bool for whether to use single wire mode
|
||||
void setEnabled(bool); //whether this bus should be enabled or not.
|
||||
int getSpeed();
|
||||
bool isListenOnly();
|
||||
bool isSingleWire();
|
||||
bool isActive();
|
||||
};
|
||||
|
||||
#endif // CANBus_H
|
||||
@@ -1,133 +0,0 @@
|
||||
#include "canconnection.h"
|
||||
|
||||
CAN_Bus::CAN_Bus()
|
||||
{
|
||||
speed = 250000;
|
||||
listenOnly = false;
|
||||
singleWire = false;
|
||||
active = false;
|
||||
connection = NULL;
|
||||
busNum = 0;
|
||||
}
|
||||
|
||||
void CAN_Bus::setSpeed(int newSpeed)
|
||||
{
|
||||
speed = newSpeed;
|
||||
}
|
||||
|
||||
void CAN_Bus::setListenOnly(bool mode)
|
||||
{
|
||||
listenOnly = mode;
|
||||
}
|
||||
|
||||
void CAN_Bus::setSingleWire(bool mode)
|
||||
{
|
||||
singleWire = mode;
|
||||
}
|
||||
|
||||
void CAN_Bus::setEnabled(bool mode)
|
||||
{
|
||||
active = mode;
|
||||
}
|
||||
|
||||
void CAN_Bus::setConnection(CANConnection *conn)
|
||||
{
|
||||
connection = conn;
|
||||
}
|
||||
|
||||
void CAN_Bus::setBusNum(int num)
|
||||
{
|
||||
busNum = num;
|
||||
}
|
||||
|
||||
int CAN_Bus::getSpeed()
|
||||
{
|
||||
return speed;
|
||||
}
|
||||
|
||||
int CAN_Bus::getBusNum()
|
||||
{
|
||||
return busNum;
|
||||
}
|
||||
|
||||
bool CAN_Bus::isListenOnly()
|
||||
{
|
||||
return listenOnly;
|
||||
}
|
||||
|
||||
bool CAN_Bus::isSingleWire()
|
||||
{
|
||||
return singleWire;
|
||||
}
|
||||
|
||||
bool CAN_Bus::isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
CANConnection* CAN_Bus::getConnection()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
CANConnection::CANConnection(CANFrameModel *pModel, int base)
|
||||
{
|
||||
model = pModel;
|
||||
numBuses = getNumBuses();
|
||||
busBase = base;
|
||||
}
|
||||
|
||||
int CANConnection::getNumBuses()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CANConnection::getBusBase()
|
||||
{
|
||||
return busBase;
|
||||
}
|
||||
|
||||
QString CANConnection::getConnTypeName()
|
||||
{
|
||||
return QString("Generic");
|
||||
}
|
||||
|
||||
QString CANConnection::getConnPortName()
|
||||
{
|
||||
return portName;
|
||||
}
|
||||
|
||||
void CANConnection::run()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CANConnection::sendFrame(const CANFrame * frame)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CANConnection::sendFrameBatch(const QList<CANFrame> *frames)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CANConnection::updatePortName(QString portName)
|
||||
{
|
||||
this->portName = portName;
|
||||
}
|
||||
|
||||
void CANConnection::stopFrameCapture(int bus)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CANConnection::startFrameCapture(int bus)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CANConnection::updateBusSettings(CAN_Bus *bus)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
#ifndef CANCONNECTION_H
|
||||
#define CANCONNECTION_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include "can_structs.h"
|
||||
#include "canframemodel.h"
|
||||
|
||||
class CANConnection;
|
||||
|
||||
class CAN_Bus
|
||||
{
|
||||
public:
|
||||
CAN_Bus();
|
||||
int busNum;
|
||||
int speed;
|
||||
bool listenOnly;
|
||||
bool singleWire;
|
||||
bool active; //is this bus turned on?
|
||||
CANConnection *connection;
|
||||
|
||||
void setSpeed(int); // new speed
|
||||
void setListenOnly(bool); //bool for whether to only listen
|
||||
void setSingleWire(bool); //bool for whether to use single wire mode
|
||||
void setEnabled(bool); //whether this bus should be enabled or not.
|
||||
void setConnection(CANConnection *);
|
||||
void setBusNum(int);
|
||||
int getSpeed();
|
||||
int getBusNum();
|
||||
bool isListenOnly();
|
||||
bool isSingleWire();
|
||||
bool isActive();
|
||||
CANConnection *getConnection();
|
||||
};
|
||||
|
||||
|
||||
//Gentle reminder, CANConnection objects run in their own thread (each one, different thread)
|
||||
//so, for the love of God, do not try to access them directly.
|
||||
//Use the signal/slots system to do indirect calls.
|
||||
//Please and thank you.
|
||||
class CANConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CANConnection(CANFrameModel *, int);
|
||||
virtual int getNumBuses();
|
||||
int getBusBase();
|
||||
virtual QString getConnTypeName();
|
||||
QString getConnPortName();
|
||||
|
||||
signals:
|
||||
void error(const QString &);
|
||||
void frameUpdateRapid(int);
|
||||
void frameUpdate(int);
|
||||
void connectionSuccess(CANConnection *);
|
||||
void connectionFailure(CANConnection *);
|
||||
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
|
||||
|
||||
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
|
||||
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
|
||||
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
|
||||
//being passed. Just set for things that really are being updated.
|
||||
void busStatus(int, int, int);
|
||||
|
||||
public slots:
|
||||
virtual void run();
|
||||
virtual void sendFrame(const CANFrame *);
|
||||
virtual void sendFrameBatch(const QList<CANFrame> *);
|
||||
virtual void updatePortName(QString); //string version of the port to connect to. This base doesnt know a thing about this value
|
||||
virtual void stopFrameCapture(int); //pass bus number
|
||||
virtual void startFrameCapture(int); //pass bus number. Only if stopped. Defaults to started anyway
|
||||
virtual void updateBusSettings(CAN_Bus *bus); //reference to the bus that changed.
|
||||
|
||||
protected:
|
||||
bool quit;
|
||||
int numBuses;
|
||||
int busBase; //first bus this class is supposed to handle
|
||||
QString portName; //for easy access later on
|
||||
QString connType; //what kind of connection this is (socketcan, kvaser, etc)
|
||||
bool isConnected; //is the whole device connected? (Is the code connected to the device itself)
|
||||
CANFrameModel *model;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTION_H
|
||||
@@ -1,28 +0,0 @@
|
||||
#include "canconnection.h"
|
||||
#include "canconnectioncontainer.h"
|
||||
|
||||
CANConnectionContainer::CANConnectionContainer(CANConnection *conn)
|
||||
{
|
||||
thread = new QThread();
|
||||
connection = conn;
|
||||
connection->moveToThread(thread);
|
||||
|
||||
connect(thread, &QThread::finished, conn, &QObject::deleteLater);
|
||||
connect(thread, &QThread::started, conn, &CANConnection::run); //setup timers within the proper thread
|
||||
connect(conn, &CANConnection::frameUpdateRapid, MainWindow::getReference(), &MainWindow::gotFrames, Qt::QueuedConnection);
|
||||
connect(MainWindow::getReference(), &MainWindow::sendCANFrame, conn, &CANConnection::sendFrame, Qt::QueuedConnection);
|
||||
thread->start();
|
||||
thread->setPriority(QThread::HighPriority);
|
||||
}
|
||||
|
||||
CANConnectionContainer::~CANConnectionContainer()
|
||||
{
|
||||
//have to stop the actual execution first before deleting
|
||||
delete thread;
|
||||
delete connection;
|
||||
}
|
||||
|
||||
CANConnection* CANConnectionContainer::getRef()
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifndef CANCONNECTIONCONTAINER_H
|
||||
#define CANCONNECTIONCONTAINER_H
|
||||
|
||||
#include "canconnection.h"
|
||||
#include <Qt>
|
||||
#include <QThread>
|
||||
#include "mainwindow.h"
|
||||
|
||||
class CANConnectionContainer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CANConnectionContainer(CANConnection *conn);
|
||||
~CANConnectionContainer();
|
||||
|
||||
CANConnection* getRef();
|
||||
|
||||
private:
|
||||
CANConnection *connection;
|
||||
QThread *thread;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTIONCONTAINER_H
|
||||
+88
-67
@@ -1,5 +1,4 @@
|
||||
#include "canconnection.h"
|
||||
#include "canconnectioncontainer.h"
|
||||
#include "connections/canconnection.h"
|
||||
#include "canconnectionmodel.h"
|
||||
|
||||
CANConnectionModel::CANConnectionModel(QObject *parent)
|
||||
@@ -7,11 +6,6 @@ CANConnectionModel::CANConnectionModel(QObject *parent)
|
||||
{
|
||||
}
|
||||
|
||||
void CANConnectionModel::refreshView()
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
@@ -41,6 +35,9 @@ QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation
|
||||
return QString(tr("Single Wire"));
|
||||
break;
|
||||
case 6:
|
||||
return QString(tr("Status"));
|
||||
break;
|
||||
case 7:
|
||||
return QString(tr("Active"));
|
||||
break;
|
||||
}
|
||||
@@ -52,100 +49,124 @@ QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int CANConnectionModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return buses.count();
|
||||
}
|
||||
|
||||
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return 7;
|
||||
}
|
||||
|
||||
|
||||
int CANConnectionModel::rowCount(const QModelIndex &parent) const {
|
||||
int rows=0;
|
||||
QList<CANConnection*>::const_iterator iter;
|
||||
|
||||
for (iter = mConns.begin() ; iter != mConns.end() ; ++iter) {
|
||||
rows+=(*iter)->getNumBuses();
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (index.row() >= (buses.count()))
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
CAN_Bus bus = buses[index.row()];
|
||||
CANConnection *conn = bus.connection;
|
||||
int busId;
|
||||
CANConnection *conn_p = getAtIdx(index.row(), busId);
|
||||
if(!conn_p)
|
||||
return QVariant();
|
||||
|
||||
CANBus bus;
|
||||
bool ret;
|
||||
ret = conn_p->getBusSettings(busId, bus);
|
||||
if(!ret) return QVariant();
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case 0: //bus
|
||||
return QString::number(bus.busNum);
|
||||
break;
|
||||
case 1: //type
|
||||
if (conn) return conn->getConnTypeName();
|
||||
else qDebug() << "Tried to show connection type but connection was NULL";
|
||||
break;
|
||||
case 2: //port
|
||||
if (conn) return conn->getConnPortName();
|
||||
else qDebug() << "Tried to show connection port but connection was NULL";
|
||||
break;
|
||||
case 3: //speed
|
||||
return QString::number(bus.speed);
|
||||
break;
|
||||
case 4: //Listen Only
|
||||
if (bus.listenOnly) return QString("True");
|
||||
else return QString("False");
|
||||
break;
|
||||
case 5: //Single Wire
|
||||
if (bus.singleWire) return QString("True");
|
||||
else return QString("False");
|
||||
break;
|
||||
case 6: //Active
|
||||
if (bus.active) return QString("True");
|
||||
else return QString("False");
|
||||
break;
|
||||
default:
|
||||
return QVariant();
|
||||
case 0: //bus
|
||||
return QString::number(busId);
|
||||
break;
|
||||
case 1: //type
|
||||
if (conn_p)
|
||||
switch (conn_p->getType()) {
|
||||
case CANCon::KVASER: return "KVASER";
|
||||
case CANCon::SOCKETCAN: return "SocketCAN";
|
||||
case CANCon::GVRET_SERIAL: return "GVRET";
|
||||
default: {}
|
||||
}
|
||||
else qDebug() << "Tried to show connection type but connection was NULL";
|
||||
break;
|
||||
case 2: //port
|
||||
if (conn_p) return conn_p->getPort();
|
||||
else qDebug() << "Tried to show connection port but connection was NULL";
|
||||
break;
|
||||
case 3: //speed
|
||||
return QString::number(bus.speed);
|
||||
case 4: //Listen Only
|
||||
return (bus.listenOnly) ? "True" : "False";
|
||||
case 5: //Single Wire
|
||||
return (bus.singleWire) ? "True" : "False";
|
||||
case 6: //Status
|
||||
return (conn_p->getStatus()==CANCon::CONNECTED) ? "Connected" : "Not Connected";
|
||||
case 7: //Active
|
||||
return (bus.active) ? "True" : "False";
|
||||
default: {}
|
||||
}
|
||||
}
|
||||
else
|
||||
return QVariant();
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CANConnectionModel::addConnection(CANConnection *conn)
|
||||
{
|
||||
CAN_Bus bus;
|
||||
CANConnectionContainer *cont = new CANConnectionContainer(conn);
|
||||
connections.append(cont);
|
||||
}
|
||||
|
||||
void CANConnectionModel::addBus(CAN_Bus &bus)
|
||||
void CANConnectionModel::add(CANConnection* pConn_p)
|
||||
{
|
||||
beginResetModel();
|
||||
buses.append(bus);
|
||||
mConns.append(pConn_p);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
CAN_Bus* CANConnectionModel::getBus(int bus)
|
||||
|
||||
void CANConnectionModel::remove(CANConnection* pConn_p)
|
||||
{
|
||||
if (bus < 0) return NULL;
|
||||
if (bus >= buses.count()) return NULL;
|
||||
return &buses[bus];
|
||||
beginResetModel();
|
||||
mConns.removeOne(pConn_p);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
CANConnection* CANConnectionModel::getConnection(int conn)
|
||||
|
||||
QList<CANConnection*>& CANConnectionModel::getConnections()
|
||||
{
|
||||
if (conn < 0) return NULL;
|
||||
if (conn >= connections.count()) return NULL;
|
||||
return connections[conn]->getRef();
|
||||
return mConns;
|
||||
}
|
||||
|
||||
CAN_Bus* CANConnectionModel::findBusByNum(int bus)
|
||||
|
||||
CANConnection* CANConnectionModel::getAtIdx(int pIdx, int& pBusId) const
|
||||
{
|
||||
for (int i = 0; i < buses.count(); i++)
|
||||
{
|
||||
if (buses[i].busNum == bus)
|
||||
{
|
||||
return &buses[i];
|
||||
if (pIdx < 0)
|
||||
return NULL;
|
||||
|
||||
int i=0;
|
||||
QList<CANConnection*>::const_iterator iter = mConns.begin();
|
||||
|
||||
for (iter = mConns.begin() ; iter != mConns.end() ; ++iter) {
|
||||
if( i <= pIdx && pIdx < i+(*iter)->getNumBuses() ) {
|
||||
pBusId = pIdx - i;
|
||||
return (*iter);
|
||||
}
|
||||
|
||||
i+= (*iter)->getNumBuses();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void CANConnectionModel::refreshView()
|
||||
{
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,12 +1,13 @@
|
||||
#ifndef CANCONNECTIONMODEL_H
|
||||
#define CANCONNECTIONMODEL_H
|
||||
|
||||
#include "canconnection.h"
|
||||
#include "canconnectioncontainer.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
class CANConnectionContainer;
|
||||
#include "canbus.h"
|
||||
#include "connections/canconnection.h"
|
||||
#include "connectionwindow.h"
|
||||
|
||||
|
||||
class CANConnectionModel : public QAbstractTableModel
|
||||
{
|
||||
@@ -18,22 +19,21 @@ public:
|
||||
// Header:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
|
||||
int rowCount(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;
|
||||
|
||||
void addConnection(CANConnection *conn);
|
||||
void addBus(CAN_Bus &bus);
|
||||
CAN_Bus* getBus(int bus);
|
||||
CANConnection* getConnection(int conn);
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
void add(CANConnection* pConn_p);
|
||||
void remove(CANConnection* pConn_p);
|
||||
|
||||
QList<CANConnection*>& getConnections();
|
||||
CANConnection* getAtIdx(int, int&) const;
|
||||
void refreshView();
|
||||
|
||||
private:
|
||||
QList<CANConnectionContainer *> connections;
|
||||
QList<CAN_Bus> buses;
|
||||
|
||||
CAN_Bus *findBusByNum(int bus);
|
||||
QList<CANConnection*> mConns;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTIONMODEL_H
|
||||
|
||||
+3
-1
@@ -281,8 +281,10 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void CANFrameModel::addFrame(const CANFrame &frame, bool autoRefresh = false)
|
||||
|
||||
void CANFrameModel::addFrame(CANFrame& frame, bool autoRefresh = false)
|
||||
{
|
||||
/*TODO: remove mutex */
|
||||
mutex.lock();
|
||||
CANFrame tempFrame;
|
||||
tempFrame = frame;
|
||||
|
||||
+3
-1
@@ -23,7 +23,6 @@ public:
|
||||
int columnCount(const QModelIndex &) const;
|
||||
int totalFrameCount();
|
||||
|
||||
void addFrame(const CANFrame &, bool);
|
||||
void sendRefresh();
|
||||
void sendRefresh(int);
|
||||
void sendBulkRefresh(int);
|
||||
@@ -46,6 +45,9 @@ public:
|
||||
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
|
||||
const QMap<int, bool> *getFiltersReference() const; //this neither
|
||||
|
||||
public slots:
|
||||
void addFrame(CANFrame&, bool);
|
||||
|
||||
signals:
|
||||
void updatedFiltersList();
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CANCONCONST_H
|
||||
#define CANCONCONST_H
|
||||
|
||||
namespace CANCon {
|
||||
|
||||
/**
|
||||
* @brief The status enum
|
||||
*/
|
||||
enum status
|
||||
{
|
||||
NOT_CONNECTED, /*!< device is not connected */
|
||||
CONNECTED /*!< device is connected */
|
||||
};
|
||||
|
||||
enum type
|
||||
{
|
||||
GVRET_SERIAL,
|
||||
KVASER,
|
||||
SOCKETCAN,
|
||||
NONE
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CANCONCONST_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <QString>
|
||||
#include "canconfactory.h"
|
||||
#include "socketcan.h"
|
||||
#include "gvretserial.h"
|
||||
|
||||
using namespace CANCon;
|
||||
|
||||
CANConnection* CanConFactory::create(type pType, QString pPortName)
|
||||
{
|
||||
switch(pType) {
|
||||
case SOCKETCAN:
|
||||
return new SocketCan(pPortName);
|
||||
case GVRET_SERIAL:
|
||||
return new GVRetSerial(pPortName);
|
||||
default: {}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef CANCONFACTORY_H
|
||||
#define CANCONFACTORY_H
|
||||
|
||||
#include "canconconst.h"
|
||||
#include "canconnection.h"
|
||||
|
||||
class CanConFactory
|
||||
{
|
||||
public:
|
||||
static CANConnection* create(CANCon::type, QString pPortName);
|
||||
};
|
||||
|
||||
#endif // CANCONFACTORY_H
|
||||
@@ -0,0 +1,245 @@
|
||||
#include <QThread>
|
||||
#include "canconnection.h"
|
||||
|
||||
CANConnection::CANConnection(QString pPort,
|
||||
CANCon::type pType,
|
||||
int pNumBuses,
|
||||
int pQueueLen,
|
||||
bool pUseThread) :
|
||||
mQueue(),
|
||||
mNumBuses(pNumBuses),
|
||||
mPort(pPort),
|
||||
mType(pType),
|
||||
mIsCapSuspended(false),
|
||||
mStatus(CANCon::NOT_CONNECTED),
|
||||
mThread_p(NULL)
|
||||
{
|
||||
qDebug() << "CANConnection()";
|
||||
|
||||
/* register types */
|
||||
qRegisterMetaType<CANBus>("CANBus");
|
||||
qRegisterMetaType<CANFrame>("CANFrame");
|
||||
qRegisterMetaType<CANCon::status>("CANCon::status");
|
||||
|
||||
/* set queue size */
|
||||
mQueue.setSize(pQueueLen); /*TODO add check on returned value */
|
||||
|
||||
/* allocate buses */
|
||||
mBus = new CANBus[mNumBuses];
|
||||
mConfigured = new bool[mNumBuses];
|
||||
|
||||
for(int i=0 ; i<mNumBuses ; i++)
|
||||
mConfigured[i] = false;
|
||||
|
||||
/* if needed, create a thread and move ourself into it */
|
||||
if(pUseThread) {
|
||||
mThread_p = new QThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CANConnection::~CANConnection()
|
||||
{
|
||||
qDebug() << "~CANConnection()";
|
||||
/* stop and delete thread */
|
||||
if(mThread_p) {
|
||||
mThread_p->quit();
|
||||
mThread_p->wait();
|
||||
delete mThread_p;
|
||||
mThread_p = NULL;
|
||||
}
|
||||
|
||||
/* delete bus table */
|
||||
delete[] mBus;
|
||||
mBus = NULL;
|
||||
/* configured table */
|
||||
delete[] mConfigured;
|
||||
mConfigured = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::start()
|
||||
{
|
||||
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(start()));
|
||||
/* start the thread */
|
||||
mThread_p->start(QThread::HighPriority);
|
||||
return;
|
||||
}
|
||||
|
||||
/* in multithread case, this will be called before entering thread event loop */
|
||||
return piStarted();
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::suspend(bool pSuspend)
|
||||
{
|
||||
/* execute in mThread_p context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "suspend",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(bool, pSuspend));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSuspend(pSuspend);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::stop()
|
||||
{
|
||||
/* 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, "stop",
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::getBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
bool ret;
|
||||
QMetaObject::invokeMethod(this, "getBusSettings",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, ret),
|
||||
Q_ARG(int , pBusIdx),
|
||||
Q_ARG(CANBus& , pBus));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return piGetBusSettings(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::setBusSettings(int pBusIdx, CANBus pBus)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "setBusSettings",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(int, pBusIdx),
|
||||
Q_ARG(CANBus, pBus));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSetBusSettings(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::sendFrame(const CANFrame& pFrame)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "sendFrame",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const CANFrame&, pFrame));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSendFrame(pFrame);
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::sendFrameBatch(const QList<CANFrame>& pFrames)
|
||||
{
|
||||
/* make sure we execute in mThread context */
|
||||
if( mThread_p && (mThread_p != QThread::currentThread()) ) {
|
||||
QMetaObject::invokeMethod(this, "sendFrameBatch",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(const QList<CANFrame>&, pFrames));
|
||||
return;
|
||||
}
|
||||
|
||||
return piSendFrameBatch(pFrames);
|
||||
}
|
||||
|
||||
|
||||
int CANConnection::getNumBuses() {
|
||||
return mNumBuses;
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::isConfigured(int pBusId) {
|
||||
if( pBusId < 0 || pBusId >= mNumBuses)
|
||||
return false;
|
||||
return mConfigured[pBusId];
|
||||
}
|
||||
|
||||
void CANConnection::setConfigured(int pBusId, bool pConfigured) {
|
||||
if( pBusId < 0 || pBusId >= mNumBuses)
|
||||
return;
|
||||
mConfigured[pBusId] = pConfigured;
|
||||
}
|
||||
|
||||
|
||||
bool CANConnection::getBusConfig(int pBusId, CANBus& pBus) {
|
||||
if( pBusId < 0 || pBusId >= mNumBuses || !isConfigured(pBusId))
|
||||
return false;
|
||||
|
||||
pBus = mBus[pBusId];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::setBusConfig(int pBusId, CANBus& pBus) {
|
||||
if( pBusId < 0 || pBusId >= mNumBuses)
|
||||
return;
|
||||
|
||||
mConfigured[pBusId] = true;
|
||||
mBus[pBusId] = pBus;
|
||||
}
|
||||
|
||||
|
||||
QString CANConnection::getPort() {
|
||||
return mPort;
|
||||
}
|
||||
|
||||
|
||||
LFQueue<CANFrame>& CANConnection::getQueue() {
|
||||
return mQueue;
|
||||
}
|
||||
|
||||
|
||||
CANCon::type CANConnection::getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
|
||||
CANCon::status CANConnection::getStatus() {
|
||||
return (CANCon::status) mStatus.load();
|
||||
}
|
||||
|
||||
|
||||
void CANConnection::setStatus(CANCon::status pStatus) {
|
||||
mStatus.store(pStatus);
|
||||
}
|
||||
|
||||
bool CANConnection::isCapSuspended() {
|
||||
return mIsCapSuspended;
|
||||
}
|
||||
|
||||
void CANConnection::setCapSuspended(bool pIsSuspended) {
|
||||
mIsCapSuspended = pIsSuspended;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
#ifndef CANCONNECTION_H
|
||||
#define CANCONNECTION_H
|
||||
|
||||
#include <Qt>
|
||||
#include <QObject>
|
||||
#include "utils/lfqueue.h"
|
||||
#include "can_structs.h"
|
||||
#include "canbus.h"
|
||||
#include "canconconst.h"
|
||||
|
||||
|
||||
class CANConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief CANConnection constructor
|
||||
* @param pPort: string containing port name
|
||||
* @param pType: the type of connection @ref CANCon::type
|
||||
* @param pNumBuses: the number of buses the device has
|
||||
* @param pQueueLen: the length of the lock free queue to use
|
||||
* @param pUseThread: if set to true, object will be execute in a dedicated thread
|
||||
*/
|
||||
CANConnection(QString pPort,
|
||||
CANCon::type pType,
|
||||
int pNumBuses,
|
||||
int pQueueLen,
|
||||
bool pUseThread);
|
||||
/**
|
||||
* @brief CANConnection destructor
|
||||
*/
|
||||
|
||||
virtual ~CANConnection();
|
||||
|
||||
/**
|
||||
* @brief getNumBuses
|
||||
* @return returns the number of buses of the device
|
||||
*/
|
||||
int getNumBuses();
|
||||
|
||||
/**
|
||||
* @brief getPort
|
||||
* @return returns the port name of the device
|
||||
*/
|
||||
QString getPort();
|
||||
|
||||
/**
|
||||
* @brief getQueue
|
||||
* @return the lock free queue of the device
|
||||
*/
|
||||
LFQueue<CANFrame>& getQueue();
|
||||
|
||||
/**
|
||||
* @brief getType
|
||||
* @return the @ref CANCon::type of the device
|
||||
*/
|
||||
CANCon::type getType();
|
||||
|
||||
/**
|
||||
* @brief getStatus
|
||||
* @return the @ref CANCon::status of the device (either connected or not)
|
||||
*/
|
||||
CANCon::status getStatus();
|
||||
|
||||
|
||||
signals:
|
||||
/*not implemented yet */
|
||||
void error(const QString &);
|
||||
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
|
||||
|
||||
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
|
||||
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
|
||||
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
|
||||
//being passed. Just set for things that really are being updated.
|
||||
void busStatus(int, int, int);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
void status(CANCon::status pStatus);
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
* @brief start the device. This calls piStarted
|
||||
* @note starts the working thread if required (piStarted is called in the working thread context)
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* @brief stop the device. This calls piStop
|
||||
* @note if a working thread is used, piStop is called before exiting the working thread
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief setBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
* @note this calls piSetBusSettings in the working thread context (if one has been started)
|
||||
*/
|
||||
void setBusSettings(int pBusIdx, CANBus pBus);
|
||||
|
||||
/**
|
||||
* @brief getBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be retrieved
|
||||
* @param pBus: the CANBus struct to fill with information
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
* @note this calls piGetBusSettings in the working thread context (if one has been started)
|
||||
*/
|
||||
bool getBusSettings(int pBusIdx, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief suspends/restarts data capture
|
||||
* @param pSuspend: suspends capture if true else restarts it
|
||||
* @note this calls piSuspend (in the working thread context if one has been started)
|
||||
* @note the caller shall not access the queue when capture is suspended, it is then safe for callee to flush the queue
|
||||
*/
|
||||
void suspend(bool pSuspend);
|
||||
|
||||
/**
|
||||
* @brief provides device with the frame to send
|
||||
* @param pFrame: the frame to send
|
||||
* @note this calls piSendFrame (in the working thread context if one has been started)
|
||||
*/
|
||||
void sendFrame(const CANFrame& pFrame);
|
||||
|
||||
/**
|
||||
* @brief provides device with a list of frames to send
|
||||
* @param pFrame: the list of frames to send
|
||||
* @note this calls piSendFrameBatch (in the working thread context if one has been started)
|
||||
*/
|
||||
void sendFrameBatch(const QList<CANFrame>& pFrames);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief setStatus
|
||||
* @param pStatus: the status to set
|
||||
*/
|
||||
void setStatus(CANCon::status pStatus);
|
||||
|
||||
/**
|
||||
* @brief isConfigured
|
||||
* @param pBusId
|
||||
* @return true if bus is configured
|
||||
*/
|
||||
bool isConfigured(int pBusId);
|
||||
|
||||
/**
|
||||
* @brief setConfigured
|
||||
* @param pBusId
|
||||
* @param pConfigured
|
||||
* @note it is not necessary to call this function to set pBusId configured, it is enough to call @ref setBusConfig
|
||||
*/
|
||||
void setConfigured(int pBusId, bool pConfigured);
|
||||
|
||||
/**
|
||||
* @brief getBusConfig
|
||||
* @param pBusId
|
||||
* @param pBus
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
*/
|
||||
bool getBusConfig(int pBusId, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief setBusConfig
|
||||
* @param pBusId: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
*/
|
||||
void setBusConfig(int pBusId, CANBus& pBus);
|
||||
|
||||
/**
|
||||
* @brief isCapSuspended
|
||||
* @return true if the capture is suspended
|
||||
*/
|
||||
bool isCapSuspended();
|
||||
|
||||
/**
|
||||
* @brief setCapSuspended
|
||||
* @param pIsSuspended
|
||||
*/
|
||||
void setCapSuspended(bool pIsSuspended);
|
||||
|
||||
protected:
|
||||
|
||||
/**************************************************************/
|
||||
/*********** protected interface to implement *******/
|
||||
/**************************************************************/
|
||||
|
||||
/**
|
||||
* @brief starts the device
|
||||
*/
|
||||
virtual void piStarted() = 0;
|
||||
|
||||
/**
|
||||
* @brief stops the device
|
||||
*/
|
||||
virtual void piStop() = 0;
|
||||
|
||||
/**
|
||||
* @brief piSetBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be set
|
||||
* @param pBus: the settings to set
|
||||
*/
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus) = 0;
|
||||
|
||||
/**
|
||||
* @brief piGetBusSettings
|
||||
* @param pBusIdx: the index of the bus for which settings have to be retrieved
|
||||
* @param pBus: the CANBus struct to fill with information
|
||||
* @return true if operation succeeds, false if pBusIdx is invalid or bus has not been configured yet
|
||||
*/
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus) = 0;
|
||||
|
||||
/**
|
||||
* @brief suspends/restarts data capture
|
||||
* @param pSuspend: suspends capture if true else restarts it
|
||||
* @note the caller will not access the queue when capture is suspended, so it is safe for callee to flush the queue
|
||||
*/
|
||||
virtual void piSuspend(bool pSuspend) = 0;
|
||||
|
||||
/**
|
||||
* @brief provides device with the frame to send
|
||||
* @param pFrame: the frame to send
|
||||
*/
|
||||
virtual void piSendFrame(const CANFrame&) = 0;
|
||||
|
||||
/**
|
||||
* @brief provides device with a list of frames to send
|
||||
* @param pFrame: the list of frames to send
|
||||
*/
|
||||
virtual void piSendFrameBatch(const QList<CANFrame>&) = 0;
|
||||
|
||||
|
||||
private:
|
||||
CANBus* mBus;
|
||||
bool* mConfigured;
|
||||
LFQueue<CANFrame> mQueue;
|
||||
const int mNumBuses;
|
||||
const QString mPort;
|
||||
const CANCon::type mType;
|
||||
bool mIsCapSuspended;
|
||||
QAtomicInt mStatus;
|
||||
QThread* mThread_p;
|
||||
};
|
||||
|
||||
#endif // CANCONNECTION_H
|
||||
@@ -0,0 +1,578 @@
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QCanBusFrame>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QSettings>
|
||||
|
||||
#include "gvretserial.h"
|
||||
|
||||
GVRetSerial::GVRetSerial(QString portName) :
|
||||
CANConnection(portName, CANCon::GVRET_SERIAL, 2, 4000, true),
|
||||
mTimer(this) /*NB: set this as parent of timer to manage it from working thread */
|
||||
{
|
||||
qDebug() << "GVRetSerial()";
|
||||
|
||||
serial = NULL;
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
gotValidated = true;
|
||||
isAutoRestart = false;
|
||||
|
||||
txTimestampBasis = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
readSettings();
|
||||
}
|
||||
|
||||
|
||||
GVRetSerial::~GVRetSerial()
|
||||
{
|
||||
stop();
|
||||
qDebug() << "~GVRetSerial()";
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piStarted()
|
||||
{
|
||||
connectDevice();
|
||||
|
||||
/* start timer */
|
||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(handleTick()));
|
||||
mTimer.setInterval(250); //tick four times per second
|
||||
mTimer.setSingleShot(false); //keep ticking
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piSuspend(bool pSuspend)
|
||||
{
|
||||
/* update capSuspended */
|
||||
setCapSuspended(pSuspend);
|
||||
|
||||
/* flush queue if we are suspended */
|
||||
if(isCapSuspended())
|
||||
getQueue().flush();
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piStop()
|
||||
{
|
||||
mTimer.stop();
|
||||
disconnectDevice();
|
||||
}
|
||||
|
||||
|
||||
bool GVRetSerial::piGetBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
return getBusConfig(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||
{
|
||||
/* sanity checks */
|
||||
if( (pBusIdx < 0) || pBusIdx >= getNumBuses())
|
||||
return;
|
||||
|
||||
/* copy bus config */
|
||||
setBusConfig(pBusIdx, bus);
|
||||
|
||||
qDebug() << "About to update bus " << pBusIdx << " on GVRET";
|
||||
if (pBusIdx == 0)
|
||||
{
|
||||
can0Baud = bus.getSpeed();
|
||||
can0Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can0Baud |= 0x40000000;
|
||||
can0Enabled = true;
|
||||
}
|
||||
else can0Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can0Baud |= 0x20000000;
|
||||
can0ListenOnly = true;
|
||||
}
|
||||
else can0ListenOnly = false;
|
||||
}
|
||||
else if (pBusIdx == 1)
|
||||
{
|
||||
can1Baud = bus.getSpeed();
|
||||
can1Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can1Baud |= 0x40000000;
|
||||
can1Enabled = true;
|
||||
}
|
||||
else can1Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can1Baud |= 0x20000000;
|
||||
can1ListenOnly = true;
|
||||
}
|
||||
else can1ListenOnly = false;
|
||||
|
||||
if (bus.isSingleWire())
|
||||
{
|
||||
can1Baud |= 0x10000000;
|
||||
deviceSingleWireMode = 1;
|
||||
}
|
||||
else deviceSingleWireMode = 0;
|
||||
}
|
||||
|
||||
/* update baud rates */
|
||||
QByteArray buffer;
|
||||
qDebug() << "Got signal to update bauds. 1: " << can0Baud <<" 2: " << can1Baud;
|
||||
buffer[0] = (char)0xF1; //start of a command over serial
|
||||
buffer[1] = 5; //setup canbus
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::piSendFrame(const CANFrame&) {}
|
||||
void GVRetSerial::piSendFrameBatch(const QList<CANFrame>&){}
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
|
||||
void GVRetSerial::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
if (settings.value("Main/ValidateComm", true).toBool())
|
||||
{
|
||||
doValidation = true;
|
||||
}
|
||||
else doValidation = false;
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::connectDevice()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
/* disconnect device */
|
||||
if(serial)
|
||||
disconnectDevice();
|
||||
|
||||
/* open new device */
|
||||
serial = new QSerialPort(QSerialPortInfo(getPort()));
|
||||
if(!serial) {
|
||||
qDebug() << "can't open serial port " << getPort();
|
||||
return;
|
||||
}
|
||||
|
||||
/* configure */
|
||||
serial->setDataBits(serial->Data8);
|
||||
serial->setFlowControl(serial->HardwareControl); //this is important though
|
||||
if (!serial->open(QIODevice::ReadWrite))
|
||||
{
|
||||
qDebug() << serial->errorString();
|
||||
}
|
||||
serial->setDataTerminalReady(true); //you do need to set these or the fan gets dirty
|
||||
serial->setRequestToSend(true);
|
||||
|
||||
|
||||
QByteArray output;
|
||||
output.append((char)0xE7); //this puts the device into binary comm mode
|
||||
output.append((char)0xE7);
|
||||
|
||||
output.append((char)0xF1); //signal we want to issue a command
|
||||
output.append((char)0x06); //request canbus stats from the board
|
||||
|
||||
output.append((char)0xF1); //another command to the GVRET
|
||||
output.append((char)0x07); //request device information
|
||||
|
||||
output.append((char)0xF1);
|
||||
output.append((char)0x08); //setting singlewire mode
|
||||
if (settings.value("Main/SingleWireMode", false).toBool())
|
||||
{
|
||||
output.append((char)0x10); //signal that we do want single wire mode
|
||||
}
|
||||
else
|
||||
{
|
||||
output.append((char)0xFF); //signal we don't want single wire mode
|
||||
}
|
||||
|
||||
output.append((char)0xF1); //yet another command
|
||||
output.append((char)0x09); //comm validation command
|
||||
|
||||
output.append((char)0xF1); //and another command
|
||||
output.append((char)0x01); //Time Sync - Not implemented until 333 but we can try
|
||||
|
||||
continuousTimeSync = true;
|
||||
|
||||
serial->write(output);
|
||||
|
||||
if(doValidation) {
|
||||
QTimer::singleShot(1000, this, SLOT(connectionTimeout()));
|
||||
}
|
||||
else {
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
|
||||
/* connect reading event */
|
||||
connect(serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::disconnectDevice() {
|
||||
if (serial != NULL)
|
||||
{
|
||||
if (serial->isOpen())
|
||||
{
|
||||
serial->clear();
|
||||
serial->close();
|
||||
|
||||
}
|
||||
serial->disconnect(); //disconnect all signals
|
||||
delete serial;
|
||||
serial = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::connectionTimeout()
|
||||
{
|
||||
//one second after trying to connect are we actually connected?
|
||||
if (CANCon::NOT_CONNECTED==getStatus()) //no?
|
||||
{
|
||||
//then emit the the failure signal and see if anyone cares
|
||||
qDebug() << "Failed to connect to GVRET at that com port";
|
||||
|
||||
disconnectDevice();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::readSerialData()
|
||||
{
|
||||
QByteArray data = serial->readAll();
|
||||
unsigned char c;
|
||||
//qDebug() << (tr("Got data from serial. Len = %0").arg(data.length()));
|
||||
for (int i = 0; i < data.length(); i++)
|
||||
{
|
||||
c = data.at(i);
|
||||
procRXChar(c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::procRXChar(unsigned char c)
|
||||
{
|
||||
switch (rx_state)
|
||||
{
|
||||
case IDLE:
|
||||
if (c == 0xF1) rx_state = GET_COMMAND;
|
||||
break;
|
||||
case GET_COMMAND:
|
||||
switch (c)
|
||||
{
|
||||
case 0: //receiving a can frame
|
||||
rx_state = BUILD_CAN_FRAME;
|
||||
rx_step = 0;
|
||||
break;
|
||||
case 1: //time sync
|
||||
rx_state = TIME_SYNC;
|
||||
rx_step = 0;
|
||||
break;
|
||||
case 2: //process a return reply for digital input states.
|
||||
rx_state = GET_DIG_INPUTS;
|
||||
rx_step = 0;
|
||||
break;
|
||||
case 3: //process a return reply for analog inputs
|
||||
rx_state = GET_ANALOG_INPUTS;
|
||||
break;
|
||||
case 4: //we set digital outputs we don't accept replies so nothing here.
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
case 5: //we set canbus specs we don't accept replies.
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
case 6: //get canbus parameters from GVRET
|
||||
rx_state = GET_CANBUS_PARAMS;
|
||||
rx_step = 0;
|
||||
break;
|
||||
case 7: //get device info
|
||||
rx_state = GET_DEVICE_INFO;
|
||||
rx_step = 0;
|
||||
break;
|
||||
case 9:
|
||||
gotValidated = true;
|
||||
//qDebug() << "Got validated";
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BUILD_CAN_FRAME:
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
buildFrame.timestamp = c;
|
||||
break;
|
||||
case 1:
|
||||
buildFrame.timestamp |= (uint)(c << 8);
|
||||
break;
|
||||
case 2:
|
||||
buildFrame.timestamp |= (uint)c << 16;
|
||||
break;
|
||||
case 3:
|
||||
buildFrame.timestamp |= (uint)c << 24;
|
||||
break;
|
||||
case 4:
|
||||
buildFrame.ID = c;
|
||||
break;
|
||||
case 5:
|
||||
buildFrame.ID |= c << 8;
|
||||
break;
|
||||
case 6:
|
||||
buildFrame.ID |= c << 16;
|
||||
break;
|
||||
case 7:
|
||||
buildFrame.ID |= c << 24;
|
||||
if ((buildFrame.ID & 1 << 31) == 1 << 31)
|
||||
{
|
||||
buildFrame.ID &= 0x7FFFFFFF;
|
||||
buildFrame.extended = true;
|
||||
}
|
||||
else buildFrame.extended = false;
|
||||
break;
|
||||
case 8:
|
||||
buildFrame.len = c & 0xF;
|
||||
if (buildFrame.len > 8) buildFrame.len = 8;
|
||||
buildFrame.bus = (c & 0xF0) >> 4;
|
||||
break;
|
||||
default:
|
||||
if (rx_step < buildFrame.len + 9)
|
||||
{
|
||||
buildFrame.data[rx_step - 9] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
buildFrame.isReceived = true;
|
||||
|
||||
if (!isCapSuspended())
|
||||
{
|
||||
/* get frame from queue */
|
||||
CANFrame* frame_p = getQueue().get();
|
||||
if(frame_p) {
|
||||
/* copy frame */
|
||||
*frame_p = buildFrame;
|
||||
/* enqueue frame */
|
||||
getQueue().queue();
|
||||
}
|
||||
else
|
||||
qDebug() << "can't get a frame, ERROR";
|
||||
|
||||
//take the time the frame came in and try to resync the time base.
|
||||
if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame.timestamp / 1000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
case TIME_SYNC: //gives a pretty good base guess for the proper timestamp. Can be refined when traffic starts to flow (if wanted)
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
buildTimeBasis = c;
|
||||
break;
|
||||
case 1:
|
||||
buildTimeBasis += ((uint32_t)c << 8);
|
||||
break;
|
||||
case 2:
|
||||
buildTimeBasis += ((uint32_t)c << 16);
|
||||
break;
|
||||
case 3:
|
||||
buildTimeBasis += ((uint32_t)c << 24);
|
||||
qDebug() << "GVRET firmware reports timestamp of " << buildTimeBasis;
|
||||
txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - ((uint64_t)buildTimeBasis / (uint64_t)1000ull);
|
||||
continuousTimeSync = false;
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
|
||||
case GET_ANALOG_INPUTS: //get 9 bytes - 2 per analog input plus checksum
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
case GET_DIG_INPUTS: //get two bytes. One for digital in status and one for checksum.
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
case GET_CANBUS_PARAMS:
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
can0Enabled = (c & 0xF);
|
||||
can0ListenOnly = (c >> 4);
|
||||
break;
|
||||
case 1:
|
||||
can0Baud = c;
|
||||
break;
|
||||
case 2:
|
||||
can0Baud |= c << 8;
|
||||
break;
|
||||
case 3:
|
||||
can0Baud |= c << 16;
|
||||
break;
|
||||
case 4:
|
||||
can0Baud |= c << 24;
|
||||
break;
|
||||
case 5:
|
||||
can1Enabled = (c & 0xF);
|
||||
can1ListenOnly = (c >> 4);
|
||||
deviceSingleWireMode = (c >> 6);
|
||||
break;
|
||||
case 6:
|
||||
can1Baud = c;
|
||||
break;
|
||||
case 7:
|
||||
can1Baud |= c << 8;
|
||||
break;
|
||||
case 8:
|
||||
can1Baud |= c << 16;
|
||||
break;
|
||||
case 9:
|
||||
can1Baud |= c << 24;
|
||||
rx_state = IDLE;
|
||||
qDebug() << "Baud 0 = " << can0Baud;
|
||||
qDebug() << "Baud 1 = " << can1Baud;
|
||||
|
||||
can0Baud |= 0x80000000;
|
||||
if (can0Enabled) can0Baud |= 0x40000000;
|
||||
if (can0ListenOnly) can0Baud |= 0x20000000;
|
||||
|
||||
can1Baud |= 0x80000000;
|
||||
if (can1Enabled) can1Baud |= 0x40000000;
|
||||
if (can1ListenOnly) can1Baud |= 0x20000000;
|
||||
if (deviceSingleWireMode > 0) can1Baud |= 0x10000000;
|
||||
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
|
||||
int can0Status = 0x78; //updating everything we can update
|
||||
int can1Status = 0x78;
|
||||
if (can0Enabled) can0Status +=1;
|
||||
if (can0ListenOnly) can0Status += 4;
|
||||
if (can1Enabled) can1Status += 1;
|
||||
if (deviceSingleWireMode > 0) can1Status += 2;
|
||||
if (can1ListenOnly) can1Status += 4;
|
||||
//emit busStatus(busBase, can0Baud & 0xFFFFF, can0Status);
|
||||
//emit busStatus(busBase + 1, can1Baud & 0xFFFFF, can1Status);
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
case GET_DEVICE_INFO:
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
deviceBuildNum = c;
|
||||
break;
|
||||
case 1:
|
||||
deviceBuildNum |= c << 8;
|
||||
break;
|
||||
case 2:
|
||||
break; //don't care about eeprom version
|
||||
case 3:
|
||||
break; //don't care about file type
|
||||
case 4:
|
||||
break; //don't care about whether it auto logs or not
|
||||
case 5:
|
||||
deviceSingleWireMode = c;
|
||||
rx_state = IDLE;
|
||||
qDebug() << "build num: " << deviceBuildNum;
|
||||
qDebug() << "single wire can: " << deviceSingleWireMode;
|
||||
emit deviceInfo(deviceBuildNum, deviceSingleWireMode);
|
||||
break;
|
||||
}
|
||||
rx_step++;
|
||||
break;
|
||||
case SET_DIG_OUTPUTS:
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
case SETUP_CANBUS:
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
case SET_SINGLEWIRE_MODE:
|
||||
rx_state = IDLE;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::handleTick()
|
||||
{
|
||||
//qDebug() << "Tick!";
|
||||
|
||||
if( CANCon::CONNECTED == getStatus() )
|
||||
{
|
||||
if (!gotValidated && doValidation)
|
||||
{
|
||||
if (serial == NULL) return;
|
||||
if (serial->isOpen()) //if it's still false we have a problem...
|
||||
{
|
||||
qDebug() << "Comm validation failed. ";
|
||||
|
||||
setStatus(CANCon::NOT_CONNECTED);
|
||||
emit status(getStatus());
|
||||
|
||||
disconnectDevice(); //start by stopping everything.
|
||||
//Then wait 500ms and restart the connection automatically
|
||||
QTimer::singleShot(500, this, SLOT(connectDevice()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doValidation && serial && serial->isOpen()) sendCommValidation();
|
||||
}
|
||||
|
||||
|
||||
void GVRetSerial::sendCommValidation()
|
||||
{
|
||||
QByteArray output;
|
||||
|
||||
gotValidated = false;
|
||||
output.append((char)0xF1); //another command to the GVRET
|
||||
output.append((char)0x09); //request a reply to get validation
|
||||
//send it twice for good measure.
|
||||
output.append((char)0xF1); //another command to the GVRET
|
||||
output.append((char)0x09); //request a reply to get validation
|
||||
|
||||
serial->write(output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
#ifndef GVRETSERIAL_H
|
||||
#define GVRETSERIAL_H
|
||||
|
||||
#include <QSerialPort>
|
||||
#include <QCanBusDevice>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
/*************/
|
||||
#include <QDateTime>
|
||||
/*************/
|
||||
|
||||
|
||||
#include "canframemodel.h"
|
||||
#include "canconnection.h"
|
||||
|
||||
|
||||
namespace SERIALSTATE {
|
||||
|
||||
enum STATE //keep this enum synchronized with the Arduino firmware project
|
||||
{
|
||||
IDLE,
|
||||
GET_COMMAND,
|
||||
BUILD_CAN_FRAME,
|
||||
TIME_SYNC,
|
||||
GET_DIG_INPUTS,
|
||||
GET_ANALOG_INPUTS,
|
||||
SET_DIG_OUTPUTS,
|
||||
SETUP_CANBUS,
|
||||
GET_CANBUS_PARAMS,
|
||||
GET_DEVICE_INFO,
|
||||
SET_SINGLEWIRE_MODE
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
using namespace SERIALSTATE;
|
||||
class GVRetSerial : public CANConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GVRetSerial(QString portName);
|
||||
virtual ~GVRetSerial();
|
||||
|
||||
signals:
|
||||
void error(const QString &);
|
||||
|
||||
void status(CANCon::status);
|
||||
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
|
||||
|
||||
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
|
||||
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
|
||||
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
|
||||
//being passed. Just set for things that really are being updated.
|
||||
void busStatus(int, int, int);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void piStarted();
|
||||
virtual void piStop();
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus);
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus);
|
||||
virtual void piSuspend(bool pSuspend);
|
||||
virtual void piSendFrame(const CANFrame&) ;
|
||||
virtual void piSendFrameBatch(const QList<CANFrame>&);
|
||||
|
||||
void disconnectDevice();
|
||||
|
||||
private slots:
|
||||
void connectDevice();
|
||||
void connectionTimeout();
|
||||
void readSerialData();
|
||||
void handleTick();
|
||||
|
||||
private:
|
||||
void readSettings();
|
||||
void procRXChar(unsigned char);
|
||||
void sendCommValidation();
|
||||
|
||||
protected:
|
||||
QTimer mTimer;
|
||||
QThread mThread;
|
||||
|
||||
|
||||
bool doValidation;
|
||||
bool gotValidated;
|
||||
bool isAutoRestart;
|
||||
bool continuousTimeSync;
|
||||
QSerialPort *serial;
|
||||
int framesRapid;
|
||||
STATE rx_state;
|
||||
int rx_step;
|
||||
CANFrame buildFrame;
|
||||
int can0Baud, can1Baud;
|
||||
bool can0Enabled, can1Enabled;
|
||||
bool can0ListenOnly, can1ListenOnly;
|
||||
int deviceBuildNum;
|
||||
int deviceSingleWireMode;
|
||||
uint64_t txTimestampBasis;
|
||||
uint32_t buildTimeBasis;
|
||||
};
|
||||
|
||||
#endif // GVRETSERIAL_H
|
||||
@@ -0,0 +1,223 @@
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QCanBusFrame>
|
||||
|
||||
#include "socketcan.h"
|
||||
|
||||
|
||||
|
||||
/***********************************/
|
||||
/**** class definition ****/
|
||||
/***********************************/
|
||||
|
||||
SocketCan::SocketCan(QString portName) :
|
||||
CANConnection(portName, CANCon::SOCKETCAN, 1, 4000, true),
|
||||
mDev_p(NULL),
|
||||
mTimer(this) /*NB: set connection as parent of timer to manage it from working thread */
|
||||
{
|
||||
qDebug() << "SocketCan()";
|
||||
}
|
||||
|
||||
|
||||
SocketCan::~SocketCan()
|
||||
{
|
||||
stop();
|
||||
qDebug() << "~SocketCan()";
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piStarted()
|
||||
{
|
||||
connect(&mTimer, SIGNAL(timeout()), this, SLOT(testConnection()));
|
||||
mTimer.setInterval(1000);
|
||||
mTimer.setSingleShot(false); //keep ticking
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piSuspend(bool pSuspend)
|
||||
{
|
||||
/* update capSuspended */
|
||||
setCapSuspended(pSuspend);
|
||||
|
||||
/* flush queue if we are suspended */
|
||||
if(isCapSuspended())
|
||||
getQueue().flush();
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piStop() {
|
||||
mTimer.stop();
|
||||
disconnectDevice();
|
||||
}
|
||||
|
||||
|
||||
bool SocketCan::piGetBusSettings(int pBusIdx, CANBus& pBus)
|
||||
{
|
||||
return getBusConfig(pBusIdx, pBus);
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piSetBusSettings(int pBusIdx, CANBus bus)
|
||||
{
|
||||
/* sanity checks */
|
||||
if(0 != pBusIdx)
|
||||
return;
|
||||
|
||||
/* disconnect device if we have one connected */
|
||||
if(mDev_p)
|
||||
disconnectDevice();
|
||||
|
||||
/* copy bus config */
|
||||
setBusConfig(0, bus);
|
||||
|
||||
/* if bus is not active we are done */
|
||||
if(!bus.active)
|
||||
return;
|
||||
|
||||
/* create device */
|
||||
mDev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
||||
if (!mDev_p) {
|
||||
disconnectDevice();
|
||||
qDebug() << "can't create device";
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect slots */
|
||||
connect(mDev_p, &QCanBusDevice::errorOccurred, this, &SocketCan::errorReceived);
|
||||
connect(mDev_p, &QCanBusDevice::framesWritten, this, &SocketCan::framesWritten);
|
||||
connect(mDev_p, &QCanBusDevice::framesReceived, this, &SocketCan::framesReceived);
|
||||
|
||||
/* set configuration */
|
||||
/*if (p.useConfigurationEnabled) {
|
||||
foreach (const SettingsDialog::ConfigurationItem &item, p.configurations)
|
||||
mDev->setConfigurationParameter(item.first, item.second);
|
||||
}*/
|
||||
|
||||
/* connect device */
|
||||
if (!mDev_p->connectDevice()) {
|
||||
disconnectDevice();
|
||||
qDebug() << "can't connect device";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::piSendFrame(const CANFrame&) {}
|
||||
void SocketCan::piSendFrameBatch(const QList<CANFrame>&){}
|
||||
|
||||
|
||||
/***********************************/
|
||||
/**** private methods ****/
|
||||
/***********************************/
|
||||
|
||||
|
||||
/* disconnect device */
|
||||
void SocketCan::disconnectDevice() {
|
||||
if(mDev_p) {
|
||||
mDev_p->disconnectDevice();
|
||||
delete mDev_p;
|
||||
mDev_p = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::errorReceived(QCanBusDevice::CanBusError error) const
|
||||
{
|
||||
switch (error) {
|
||||
case QCanBusDevice::ReadError:
|
||||
case QCanBusDevice::WriteError:
|
||||
case QCanBusDevice::ConnectionError:
|
||||
case QCanBusDevice::ConfigurationError:
|
||||
case QCanBusDevice::UnknownError:
|
||||
qWarning() << mDev_p->errorString();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SocketCan::framesWritten(qint64 count)
|
||||
{
|
||||
qDebug() << "Number of frames written:" << count;
|
||||
}
|
||||
|
||||
void SocketCan::framesReceived()
|
||||
{
|
||||
/* sanity checks */
|
||||
if(!mDev_p)
|
||||
return;
|
||||
|
||||
/* read frame */
|
||||
while(true)
|
||||
{
|
||||
const QCanBusFrame recFrame = mDev_p->readFrame();
|
||||
|
||||
/* exit case */
|
||||
if(!recFrame.isValid())
|
||||
return;
|
||||
|
||||
/* drop frame if capture is suspended */
|
||||
if(isCapSuspended())
|
||||
continue;
|
||||
|
||||
/* check frame */
|
||||
if(!recFrame.payload().isEmpty() &&
|
||||
recFrame.payload().length()<=8)
|
||||
{
|
||||
CANFrame* frame_p = getQueue().get();
|
||||
if(frame_p) {
|
||||
frame_p->len = recFrame.payload().length();
|
||||
frame_p->bus = 0;
|
||||
memcpy(frame_p->data, recFrame.payload().data(), frame_p->len);
|
||||
frame_p->extended = false;
|
||||
frame_p->ID = recFrame.frameId();
|
||||
frame_p->isReceived = true;
|
||||
frame_p->timestamp = recFrame.timeStamp().seconds()*1000000 + recFrame.timeStamp().microSeconds();
|
||||
|
||||
/* enqueue frame */
|
||||
getQueue().queue();
|
||||
}
|
||||
else
|
||||
qDebug() << "can't get a frame, ERROR";
|
||||
}
|
||||
else {
|
||||
qDebug() << "invalid frame";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SocketCan::testConnection() {
|
||||
QCanBusDevice* dev_p = QCanBus::instance()->createDevice("socketcan", getPort());
|
||||
|
||||
switch(getStatus())
|
||||
{
|
||||
case CANCon::CONNECTED:
|
||||
if (!dev_p || !dev_p->connectDevice()) {
|
||||
/* we have lost connectivity */
|
||||
disconnectDevice();
|
||||
|
||||
setStatus(CANCon::NOT_CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
break;
|
||||
case CANCon::NOT_CONNECTED:
|
||||
if (dev_p && dev_p->connectDevice()) {
|
||||
if(!mDev_p) {
|
||||
/* try to reconnect */
|
||||
CANBus bus;
|
||||
if(getBusConfig(0, bus))
|
||||
setBusSettings(0, bus);
|
||||
}
|
||||
/* disconnect test instance */
|
||||
dev_p->disconnectDevice();
|
||||
|
||||
setStatus(CANCon::CONNECTED);
|
||||
emit status(getStatus());
|
||||
}
|
||||
break;
|
||||
default: {}
|
||||
}
|
||||
|
||||
if(dev_p)
|
||||
delete dev_p;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef SocketCan_H
|
||||
#define SocketCan_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QCanBus>
|
||||
#include <QTimer>
|
||||
#include <qthread.h>
|
||||
|
||||
#include "canframemodel.h"
|
||||
#include "canconnection.h"
|
||||
|
||||
|
||||
class SocketCan : public CANConnection
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SocketCan(QString portName);
|
||||
virtual ~SocketCan();
|
||||
|
||||
signals:
|
||||
void error(const QString &);
|
||||
|
||||
void status(CANCon::status);
|
||||
void deviceInfo(int, int); //First param = driver version (or version of whatever you want), second param a status byte
|
||||
|
||||
//bus number, bus speed, status (bit 0 = enabled, 1 = single wire, 2 = listen only)
|
||||
//3 = Use value stored for enabled, 4 = use value passed for single wire, 5 = use value passed for listen only
|
||||
//6 = use value passed for speed. This allows bus status to be updated but set that some things aren't really
|
||||
//being passed. Just set for things that really are being updated.
|
||||
void busStatus(int, int, int);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void piStarted();
|
||||
virtual void piStop();
|
||||
virtual void piSetBusSettings(int pBusIdx, CANBus pBus);
|
||||
virtual bool piGetBusSettings(int pBusIdx, CANBus& pBus);
|
||||
virtual void piSuspend(bool pSuspend);
|
||||
virtual void piSendFrame(const CANFrame&) ;
|
||||
virtual void piSendFrameBatch(const QList<CANFrame>&);
|
||||
|
||||
void disconnectDevice();
|
||||
|
||||
private slots:
|
||||
void errorReceived(QCanBusDevice::CanBusError) const;
|
||||
void framesWritten(qint64 count);
|
||||
void framesReceived();
|
||||
void testConnection();
|
||||
|
||||
protected:
|
||||
QCanBusDevice* mDev_p;
|
||||
QTimer mTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // SocketCan_H
|
||||
+240
-116
@@ -1,6 +1,9 @@
|
||||
#include <QCanBus>
|
||||
|
||||
#include "connectionwindow.h"
|
||||
#include "ui_connectionwindow.h"
|
||||
#include <QtNetwork/QNetworkInterface>
|
||||
#include "connections/canconfactory.h"
|
||||
|
||||
|
||||
ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -10,7 +13,7 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
|
||||
settings = new QSettings();
|
||||
|
||||
qRegisterMetaType<CAN_Bus *>("CAN_Bus *");
|
||||
qRegisterMetaType<CANBus>("CANBus");
|
||||
qRegisterMetaType<const CANFrame *>("const CANFrame *");
|
||||
qRegisterMetaType<const QList<CANFrame> *>("const QList<CANFrame> *");
|
||||
|
||||
@@ -22,10 +25,11 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
ui->tableConnections->setColumnWidth(0, 50);
|
||||
ui->tableConnections->setColumnWidth(1, 110);
|
||||
ui->tableConnections->setColumnWidth(2, 110);
|
||||
ui->tableConnections->setColumnWidth(3, 150);
|
||||
ui->tableConnections->setColumnWidth(3, 110);
|
||||
ui->tableConnections->setColumnWidth(4, 75);
|
||||
ui->tableConnections->setColumnWidth(5, 75);
|
||||
ui->tableConnections->setColumnWidth(6, 75);
|
||||
ui->tableConnections->setColumnWidth(7, 75);
|
||||
|
||||
int temp = settings->value("Main/DefaultConnectionType", 0).toInt();
|
||||
|
||||
@@ -36,7 +40,6 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
ui->ckSingleWire->setChecked(settings->value("Main/SingleWireMode", false).toBool());
|
||||
|
||||
ui->cbSpeed->addItem(tr("<Default>"));
|
||||
ui->cbSpeed->addItem(tr("Disabled"));
|
||||
ui->cbSpeed->addItem(tr("125000"));
|
||||
ui->cbSpeed->addItem(tr("250000"));
|
||||
ui->cbSpeed->addItem(tr("500000"));
|
||||
@@ -44,7 +47,7 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
ui->cbSpeed->addItem(tr("33333"));
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
ui->rbSocketCAN->setEnabled(true);
|
||||
ui->rbSocketCAN->setEnabled(isSocketCanAvailable());
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -57,14 +60,38 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||
connect(ui->rbSocketCAN, &QAbstractButton::toggled, this, &ConnectionWindow::handleConnTypeChanged);
|
||||
connect(ui->btnRevert, &QPushButton::clicked, this, &ConnectionWindow::handleRevert);
|
||||
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ConnectionWindow::handleConnSelectionChanged);
|
||||
connect(connModel, &QAbstractItemModel::modelReset, this, &ConnectionWindow::handleConnSelectionChanged);
|
||||
connect(ui->btnNewConn, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn);
|
||||
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
||||
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
||||
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
||||
|
||||
|
||||
qDebug() << "Serial worker thread starting";
|
||||
|
||||
connect(&mTicker, SIGNAL(timeout()), this, SLOT(refreshCanList()));
|
||||
/* tick frequency has a huge impact on performances */
|
||||
/* TODO: make this configurable and part of the connection constructor to let connection configure the length of the queue */
|
||||
mTicker.setInterval(500); /*tick twice a second */
|
||||
mTicker.setSingleShot(false);
|
||||
mTicker.start();
|
||||
}
|
||||
|
||||
ConnectionWindow::~ConnectionWindow()
|
||||
{
|
||||
QList<CANConnection*>& conns = connModel->getConnections();
|
||||
CANConnection* conn_p;
|
||||
|
||||
/* delete connections */
|
||||
while(!conns.isEmpty()) {
|
||||
conn_p = conns.takeFirst();
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
delete connModel;
|
||||
|
||||
mTicker.stop();
|
||||
delete settings;
|
||||
delete ui;
|
||||
}
|
||||
@@ -76,6 +103,20 @@ void ConnectionWindow::showEvent(QShowEvent* event)
|
||||
handleConnTypeChanged();
|
||||
}
|
||||
|
||||
void ConnectionWindow::refreshCanList() {
|
||||
QList<CANConnection*>::iterator conn_p;
|
||||
QList<CANConnection*>& conns = connModel->getConnections();
|
||||
|
||||
CANFrame* frame_p = NULL;
|
||||
|
||||
for (conn_p = conns.begin(); conn_p != conns.end(); ++conn_p) {
|
||||
while( (frame_p = (*conn_p)->getQueue().peek() ) ) {
|
||||
canModel->addFrame(*frame_p, true);
|
||||
(*conn_p)->getQueue().dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleNewConn()
|
||||
{
|
||||
ui->tableConnections->selectionModel()->clearSelection();
|
||||
@@ -83,100 +124,113 @@ void ConnectionWindow::handleNewConn()
|
||||
handleConnSelectionChanged();
|
||||
}
|
||||
|
||||
void ConnectionWindow::setSuspendAll(bool pSuspend)
|
||||
{
|
||||
qDebug() << "setSuspendAll";
|
||||
|
||||
QList<CANConnection*>::iterator iter;
|
||||
QList<CANConnection*>& conns = connModel->getConnections();
|
||||
|
||||
for (iter = conns.begin(); iter != conns.end(); ++iter)
|
||||
(*iter)->suspend(pSuspend);
|
||||
}
|
||||
|
||||
void ConnectionWindow::setActiveAll(bool pActive)
|
||||
{
|
||||
QList<CANConnection*>::iterator iter;
|
||||
QList<CANConnection*>& conns = connModel->getConnections();
|
||||
CANBus bus;
|
||||
|
||||
for (iter = conns.begin(); iter != conns.end(); ++iter) {
|
||||
for(int i=0 ; i<(*iter)->getNumBuses() ; i++) {
|
||||
if( (*iter)->getBusSettings(i, bus) ) {
|
||||
bus.active = pActive;
|
||||
(*iter)->setBusSettings(i, bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleEnableAll()
|
||||
{
|
||||
|
||||
setActiveAll(true);
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleDisableAll()
|
||||
{
|
||||
|
||||
setActiveAll(false);
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleConnTypeChanged()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) getSerialPorts();
|
||||
if (ui->rbKvaser->isChecked()) getKvaserPorts();
|
||||
if (ui->rbSocketCAN->isChecked()) getSocketcanPorts();
|
||||
if (ui->rbGVRET->isChecked()) selectSerial();
|
||||
if (ui->rbKvaser->isChecked()) selectKvaser();
|
||||
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
|
||||
}
|
||||
|
||||
void ConnectionWindow::connectionSuccess(CANConnection *conn)
|
||||
|
||||
/* status */
|
||||
void ConnectionWindow::connectionStatus(CANCon::status pStatus)
|
||||
{
|
||||
CAN_Bus bus;
|
||||
bus.active = true;
|
||||
bus.busNum = conn->getBusBase();
|
||||
bus.connection = conn;
|
||||
bus.listenOnly = ui->ckListenOnly->isChecked();
|
||||
bus.singleWire = ui->ckSingleWire->isChecked();
|
||||
|
||||
if (ui->cbSpeed->currentIndex() < 1) bus.speed = 0; //default speed
|
||||
else if (ui->cbSpeed->currentIndex() == 1)
|
||||
{
|
||||
bus.speed = 0;
|
||||
bus.active = false;
|
||||
}
|
||||
else bus.speed = ui->cbSpeed->currentText().toInt();
|
||||
connModel->addBus(bus);
|
||||
|
||||
int numBuses = conn->getNumBuses();
|
||||
for (int i = 1; i < numBuses; i++)
|
||||
{
|
||||
bus.active = false;
|
||||
bus.listenOnly = false;
|
||||
bus.singleWire = false;
|
||||
bus.speed = 250000;
|
||||
bus.busNum = conn->getBusBase() + i;
|
||||
bus.connection = conn;
|
||||
connModel->addBus(bus);
|
||||
qDebug() << "Added bus " << bus.busNum;
|
||||
}
|
||||
qDebug() << "Connectionstatus changed";
|
||||
connModel->refreshView();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::handleOKButton()
|
||||
{
|
||||
QString conn;
|
||||
int connType = 0;
|
||||
int whichRow = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
qDebug() << "OK pressed. Row " << whichRow;
|
||||
|
||||
CANConnection* conn_p = NULL;
|
||||
|
||||
if (whichRow > -1)
|
||||
{
|
||||
//load settings from GUI into appropriate CAN_Bus entry and then send it off to the appropriate
|
||||
//CANConnection object
|
||||
CAN_Bus *bus = connModel->getBus(whichRow);
|
||||
bus->setListenOnly(ui->ckListenOnly->isChecked());
|
||||
bus->setSingleWire(ui->ckSingleWire->isChecked());
|
||||
bus->setEnabled(ui->ckEnabled->isChecked());
|
||||
if (ui->cbSpeed->currentIndex() == 1)
|
||||
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());
|
||||
if (ui->cbSpeed->currentIndex() == 0)
|
||||
{
|
||||
bus->speed = 0;
|
||||
bus->setEnabled(false);
|
||||
bus.speed = 0;
|
||||
bus.setEnabled(false);
|
||||
}
|
||||
else if (ui->cbSpeed->currentIndex() > 1)
|
||||
else if (ui->cbSpeed->currentIndex() >= 1)
|
||||
{
|
||||
bus->setSpeed(ui->cbSpeed->currentText().toInt());
|
||||
bus.setSpeed(ui->cbSpeed->currentText().toInt());
|
||||
}
|
||||
//call through signal/slot interface without using connect
|
||||
QMetaObject::invokeMethod(bus->connection, "updateBusSettings",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(CAN_Bus *, bus));
|
||||
/* update bus settings */
|
||||
conn_p->setBusSettings(busId, bus);
|
||||
|
||||
connModel->refreshView();
|
||||
}
|
||||
else //new connection
|
||||
{
|
||||
#if 0
|
||||
if (ui->rbGVRET->isChecked())
|
||||
{
|
||||
{
|
||||
|
||||
SerialWorker *serial = new SerialWorker(canModel, connModel->rowCount());
|
||||
connect(serial, SIGNAL(busStatus(int,int,int)), this, SLOT(receiveBusStatus(int,int,int)));
|
||||
connect(serial, SIGNAL(connectionSuccess(CANConnection*)), this, SLOT(connectionSuccess(CANConnection*)));
|
||||
connModel->addConnection(serial);
|
||||
CANConnectionContainer* container = new CANConnectionContainer(serial);
|
||||
|
||||
|
||||
qDebug() << "Setup initial connection object";
|
||||
|
||||
CAN_Bus bus;
|
||||
CANBus bus;
|
||||
bus.active = ui->ckEnabled->isChecked();
|
||||
bus.busNum = serial->getBusBase();
|
||||
bus.connection = serial;
|
||||
bus.container = container;
|
||||
bus.listenOnly = ui->ckListenOnly->isChecked();
|
||||
bus.singleWire = ui->ckSingleWire->isChecked();
|
||||
|
||||
@@ -187,6 +241,7 @@ void ConnectionWindow::handleOKButton()
|
||||
bus.active = false;
|
||||
}
|
||||
else bus.speed = ui->cbSpeed->currentText().toInt();
|
||||
|
||||
connModel->addBus(bus);
|
||||
|
||||
int numBuses = serial->getNumBuses();
|
||||
@@ -197,7 +252,7 @@ void ConnectionWindow::handleOKButton()
|
||||
bus.singleWire = false;
|
||||
bus.speed = 250000;
|
||||
bus.busNum = serial->getBusBase() + i;
|
||||
bus.connection = serial;
|
||||
bus.container = container;
|
||||
connModel->addBus(bus);
|
||||
qDebug() << "Added bus " << bus.busNum;
|
||||
}
|
||||
@@ -206,22 +261,45 @@ void ConnectionWindow::handleOKButton()
|
||||
QMetaObject::invokeMethod(serial, "updatePortName",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QString, ui->cbPort->currentText()));
|
||||
}
|
||||
else if (ui->rbKvaser->isChecked())
|
||||
{
|
||||
#endif
|
||||
|
||||
}
|
||||
else if (ui->rbSocketCAN->isChecked())
|
||||
{
|
||||
/* create connection */
|
||||
conn_p = CanConFactory::create(getConnectionType(), getPortName());
|
||||
if(!conn_p)
|
||||
return;
|
||||
|
||||
/* connect signal */
|
||||
connect(conn_p, SIGNAL(status(CANCon::status)),
|
||||
this, SLOT(connectionStatus(CANCon::status)));
|
||||
|
||||
/*TODO add return value and checks */
|
||||
conn_p->start();
|
||||
|
||||
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();
|
||||
|
||||
if (ui->cbSpeed->currentIndex() < 1) bus.speed = 0;
|
||||
else bus.speed = ui->cbSpeed->currentText().toInt();
|
||||
|
||||
/* update bus settings */
|
||||
conn_p->setBusSettings(i, bus);
|
||||
}
|
||||
|
||||
/* add connection to model */
|
||||
connModel->add(conn_p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::receiveBusStatus(int bus, int speed, int status)
|
||||
{
|
||||
#if 0
|
||||
qDebug() << "bus " << bus << " speed " << speed << " status " << status;
|
||||
CAN_Bus *busRef = connModel->getBus(bus);
|
||||
CANBus *busRef = connModel->getBus(bus);
|
||||
if (status & 40) busRef->setSpeed(speed);
|
||||
if (status & 8) //update enabled status
|
||||
{
|
||||
@@ -236,19 +314,22 @@ void ConnectionWindow::receiveBusStatus(int bus, int speed, int status)
|
||||
busRef->setListenOnly((status & 4)?true:false);
|
||||
}
|
||||
connModel->refreshView();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleConnSelectionChanged()
|
||||
{
|
||||
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
qDebug() << "Selection: " << selIdx;
|
||||
if (selIdx == -1)
|
||||
{
|
||||
ui->btnOK->setText(tr("Create New Connection"));
|
||||
|
||||
ui->cbPort->setEnabled(true);
|
||||
ui->rbGVRET->setEnabled(true);
|
||||
ui->rbKvaser->setEnabled(true);
|
||||
ui->rbSocketCAN->setEnabled(true);
|
||||
ui->cbSpeed->setEnabled(false);
|
||||
|
||||
ui->cbPort->setCurrentIndex(0);
|
||||
ui->ckListenOnly->setChecked(false);
|
||||
ui->ckSingleWire->setChecked(false);
|
||||
@@ -256,25 +337,43 @@ void ConnectionWindow::handleConnSelectionChanged()
|
||||
}
|
||||
else
|
||||
{
|
||||
int busId;
|
||||
bool ret;
|
||||
CANBus bus;
|
||||
CANConnection* conn_p = connModel->getAtIdx(selIdx, busId);
|
||||
if(!conn_p) return;
|
||||
ret = conn_p->getBusSettings(busId, bus);
|
||||
if(!ret) return;
|
||||
|
||||
ui->btnOK->setText(tr("Update Connection Settings"));
|
||||
|
||||
ui->cbPort->setEnabled(false);
|
||||
ui->rbGVRET->setEnabled(false);
|
||||
ui->rbKvaser->setEnabled(false);
|
||||
ui->rbSocketCAN->setEnabled(false);
|
||||
CAN_Bus *bus = connModel->getBus(selIdx);
|
||||
if (bus->connection->getConnTypeName() == "GVRET") ui->rbGVRET->setChecked(true);
|
||||
if (bus->connection->getConnTypeName() == "KVASER") ui->rbKvaser->setChecked(true);
|
||||
if (bus->connection->getConnTypeName() == "SOCKETCAN") ui->rbSocketCAN->setChecked(true);
|
||||
ui->ckListenOnly->setChecked(bus->isListenOnly());
|
||||
ui->ckSingleWire->setChecked(bus->isSingleWire());
|
||||
ui->ckEnabled->setChecked(bus->isActive());
|
||||
int speed = bus->getSpeed();
|
||||
ui->rbSocketCAN->setEnabled(false);
|
||||
ui->cbSpeed->setEnabled(true);
|
||||
|
||||
switch(conn_p->getType()) {
|
||||
case CANCon::GVRET_SERIAL: ui->rbGVRET->setChecked(true); break;
|
||||
case CANCon::KVASER: ui->rbKvaser->setChecked(true); break;
|
||||
case CANCon::SOCKETCAN: ui->rbSocketCAN->setChecked(true); break;
|
||||
default: {}
|
||||
}
|
||||
|
||||
ui->ckListenOnly->setChecked(bus.isListenOnly());
|
||||
ui->ckSingleWire->setChecked(bus.isSingleWire());
|
||||
ui->ckEnabled->setChecked(bus.isActive());
|
||||
int speed = bus.getSpeed();
|
||||
setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::getSerialPorts()
|
||||
|
||||
void ConnectionWindow::selectSerial()
|
||||
{
|
||||
/* set combobox page visible */
|
||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||
|
||||
ui->cbPort->clear();
|
||||
ports = QSerialPortInfo::availablePorts();
|
||||
|
||||
@@ -285,28 +384,19 @@ void ConnectionWindow::getSerialPorts()
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionWindow::getKvaserPorts()
|
||||
void ConnectionWindow::selectKvaser()
|
||||
{
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/* set combobox page visible */
|
||||
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConnectionWindow::getSocketcanPorts()
|
||||
void ConnectionWindow::selectSocketCan()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
|
||||
QString interfaceName;
|
||||
|
||||
ui->cbPort->clear();
|
||||
|
||||
foreach (QNetworkInterface interface, interfaces)
|
||||
{
|
||||
interfaceName = interface.name().toLower();
|
||||
qDebug() << "Interface: " << interface.name();
|
||||
if (interfaceName.contains("can"))
|
||||
{
|
||||
ui->cbPort->addItem(interfaceName);
|
||||
}
|
||||
}
|
||||
/* set edit text page visible */
|
||||
ui->stPort->setCurrentWidget(ui->etPage);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -355,16 +445,30 @@ int ConnectionWindow::getSpeed()
|
||||
|
||||
QString ConnectionWindow::getPortName()
|
||||
{
|
||||
return (ui->cbPort->currentText());
|
||||
switch( getConnectionType() ) {
|
||||
case CANCon::GVRET_SERIAL:
|
||||
case CANCon::KVASER:
|
||||
return ui->cbPort->currentText();
|
||||
case CANCon::SOCKETCAN:
|
||||
return ui->lePort->text();
|
||||
default:
|
||||
qDebug() << "getPortName: can't get port";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
ConnectionType::ConnectionType ConnectionWindow::getConnectionType()
|
||||
CANCon::type ConnectionWindow::getConnectionType()
|
||||
{
|
||||
if (ui->rbGVRET->isChecked()) return ConnectionType::GVRET_SERIAL;
|
||||
if (ui->rbKvaser->isChecked()) return ConnectionType::KVASER;
|
||||
if (ui->rbSocketCAN->isChecked()) return ConnectionType::SOCKETCAN;
|
||||
if (ui->rbGVRET->isChecked()) return CANCon::GVRET_SERIAL;
|
||||
if (ui->rbKvaser->isChecked()) return CANCon::KVASER;
|
||||
if (ui->rbSocketCAN->isChecked()) return CANCon::SOCKETCAN;
|
||||
|
||||
qDebug() << "getConnectionType: error";
|
||||
return CANCon::NONE;
|
||||
}
|
||||
|
||||
|
||||
void ConnectionWindow::setSWMode(bool mode)
|
||||
{
|
||||
ui->ckSingleWire->setChecked(mode);
|
||||
@@ -378,7 +482,21 @@ bool ConnectionWindow::getSWMode()
|
||||
|
||||
void ConnectionWindow::handleRemoveConn()
|
||||
{
|
||||
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||
if (selIdx <0) return;
|
||||
|
||||
qDebug() << "remove connection at index: " << selIdx;
|
||||
|
||||
int busId;
|
||||
CANConnection* conn_p = connModel->getAtIdx(selIdx, busId);
|
||||
if(!conn_p) return;
|
||||
|
||||
/* remove connection from model */
|
||||
connModel->remove(conn_p);
|
||||
|
||||
/* stop and delete connection */
|
||||
conn_p->stop();
|
||||
delete conn_p;
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleRevert()
|
||||
@@ -386,31 +504,37 @@ void ConnectionWindow::handleRevert()
|
||||
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleEnableAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ConnectionWindow::handleDisableAll()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ConnectionWindow::sendFrame(const CANFrame *frame)
|
||||
{
|
||||
CAN_Bus *bus = connModel->getBus(frame->bus);
|
||||
#if 0
|
||||
CANBus *bus = connModel->getBus(frame->bus);
|
||||
if (bus == NULL) return;
|
||||
QMetaObject::invokeMethod(bus->connection, "sendFrame",
|
||||
QMetaObject::invokeMethod(bus->getContainer()->getRef(), "sendFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const CANFrame *, frame));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConnectionWindow::sendFrameBatch(const QList<CANFrame> *frames)
|
||||
{
|
||||
#if 0
|
||||
if (frames->count() == 0) return;
|
||||
CAN_Bus *bus = connModel->getBus(frames->at(0).bus);
|
||||
CANBus *bus = connModel->getBus(frames->at(0).bus);
|
||||
if (bus == NULL) return;
|
||||
QMetaObject::invokeMethod(bus->connection, "sendFrameBatch",
|
||||
QMetaObject::invokeMethod(bus->getContainer()->getRef(), "sendFrameBatch",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const QList<CANFrame> *, frames));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ConnectionWindow::isSocketCanAvailable()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
foreach (const QByteArray &backend, QCanBus::instance()->plugins()) {
|
||||
if (backend == "socketcan") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,14 +1,18 @@
|
||||
#ifndef CONNECTIONWINDOW_H
|
||||
#define CONNECTIONWINDOW_H
|
||||
|
||||
#include "canconnectionmodel.h"
|
||||
|
||||
|
||||
#include <QSerialPortInfo>
|
||||
#include <QDialog>
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include "canconnection.h"
|
||||
#include "serialworker.h"
|
||||
#include <QTimer>
|
||||
//#include "canconnection_old.h"
|
||||
//#include "serialworker.h"
|
||||
#include "canconnectionmodel.h"
|
||||
#include "canframemodel.h"
|
||||
|
||||
|
||||
class CANConnectionModel;
|
||||
|
||||
@@ -16,15 +20,6 @@ namespace Ui {
|
||||
class ConnectionWindow;
|
||||
}
|
||||
|
||||
namespace ConnectionType
|
||||
{
|
||||
enum ConnectionType
|
||||
{
|
||||
GVRET_SERIAL,
|
||||
KVASER,
|
||||
SOCKETCAN
|
||||
};
|
||||
}
|
||||
|
||||
class ConnectionWindow : public QDialog
|
||||
{
|
||||
@@ -36,11 +31,11 @@ public:
|
||||
void showEvent(QShowEvent *);
|
||||
int getSpeed();
|
||||
QString getPortName(); //name of port to connect to
|
||||
ConnectionType::ConnectionType getConnectionType();
|
||||
CANCon::type getConnectionType();
|
||||
bool getSWMode();
|
||||
|
||||
signals:
|
||||
void updateBusSettings(CAN_Bus *bus);
|
||||
void updateBusSettings(CANBus *bus);
|
||||
void updatePortName(QString port);
|
||||
|
||||
public slots:
|
||||
@@ -48,6 +43,8 @@ public slots:
|
||||
void setSWMode(bool mode);
|
||||
void sendFrame(const CANFrame *);
|
||||
void sendFrameBatch(const QList<CANFrame> *);
|
||||
void setSuspendAll(bool);
|
||||
|
||||
|
||||
private slots:
|
||||
void handleOKButton();
|
||||
@@ -58,10 +55,10 @@ private slots:
|
||||
void handleDisableAll();
|
||||
void handleRevert();
|
||||
void handleNewConn();
|
||||
void handleEnableAll();
|
||||
void handleDisableAll();
|
||||
void receiveBusStatus(int bus, int speed, int status);
|
||||
void connectionSuccess(CANConnection *conn);
|
||||
void connectionStatus(CANCon::status);
|
||||
|
||||
void refreshCanList();
|
||||
|
||||
private:
|
||||
Ui::ConnectionWindow *ui;
|
||||
@@ -69,11 +66,14 @@ private:
|
||||
QSettings *settings;
|
||||
CANConnectionModel *connModel;
|
||||
CANFrameModel *canModel;
|
||||
QTimer mTicker;
|
||||
|
||||
|
||||
void getSerialPorts();
|
||||
void getKvaserPorts();
|
||||
void getSocketcanPorts();
|
||||
void selectSerial();
|
||||
void selectKvaser();
|
||||
void selectSocketCan();
|
||||
bool isSocketCanAvailable();
|
||||
void setActiveAll(bool pActive);
|
||||
};
|
||||
|
||||
#endif // CONNECTIONWINDOW_H
|
||||
|
||||
+65
-3
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1009</width>
|
||||
<height>433</height>
|
||||
<width>956</width>
|
||||
<height>527</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -129,7 +129,69 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPort"/>
|
||||
<widget class="QStackedWidget" name="stPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="cbPage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<widget class="QComboBox" name="cbPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>341</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="etPage">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lePort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="ckSingleWire">
|
||||
|
||||
+6
-8
@@ -47,7 +47,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION));
|
||||
|
||||
model = new CANFrameModel();
|
||||
model = new CANFrameModel(this); // set parent to mainwindow to prevent canframemodel to change thread (might be done by setModel but just in case)
|
||||
|
||||
ui->canFramesView->setModel(model);
|
||||
|
||||
readSettings();
|
||||
@@ -180,6 +181,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
//Automatically create the connection window so it can be updated even if we never opened it.
|
||||
connectionWindow = new ConnectionWindow(model);
|
||||
connect(connectionWindow, SIGNAL(updateConnectionSettings(QString,QString,int,int)), this, SLOT(updateConnectionSettings(QString,QString,int,int)));
|
||||
connect(this, SIGNAL(suspendCapturing(bool)), connectionWindow, SLOT(setSuspendAll(bool)));
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -510,7 +512,7 @@ void MainWindow::gotFrames(int framesSinceLastUpdate)
|
||||
|
||||
void MainWindow::addFrameToDisplay(CANFrame &frame, bool autoRefresh = false)
|
||||
{
|
||||
model->addFrame(frame, autoRefresh);
|
||||
model->addFrame(frame, autoRefresh);
|
||||
if (autoRefresh)
|
||||
{
|
||||
if (ui->cbAutoScroll->isChecked()) ui->canFramesView->scrollToBottom();
|
||||
@@ -712,15 +714,11 @@ void MainWindow::toggleCapture()
|
||||
{
|
||||
allowCapture = !allowCapture;
|
||||
if (allowCapture)
|
||||
{
|
||||
ui->btnCaptureToggle->setText("Suspend Capturing");
|
||||
emit startFrameCapturing();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->btnCaptureToggle->setText("Restart Capturing");
|
||||
emit stopFrameCapturing();
|
||||
}
|
||||
|
||||
emit suspendCapturing(!allowCapture);
|
||||
}
|
||||
|
||||
void MainWindow::connectionSucceeded(int baud0, int baud1)
|
||||
|
||||
+1
-2
@@ -92,8 +92,7 @@ public slots:
|
||||
|
||||
signals:
|
||||
void sendCANFrame(const CANFrame *, int);
|
||||
void stopFrameCapturing();
|
||||
void startFrameCapturing();
|
||||
void suspendCapturing(bool);
|
||||
|
||||
//-1 = frames cleared, -2 = a new file has been loaded (so all frames are different), otherwise # of new frames
|
||||
void framesUpdated(int numFrames); //something has updated the frame list
|
||||
|
||||
+94
-76
@@ -5,13 +5,14 @@
|
||||
#include <QTimer>
|
||||
#include <QSettings>
|
||||
|
||||
#if 0
|
||||
SerialWorker::SerialWorker(CANFrameModel *model, int base) : CANConnection(model, base)
|
||||
{
|
||||
qDebug() << "Serial Worker constructor";
|
||||
serial = NULL;
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
buildFrame = new CANFrame;
|
||||
buildFrame;
|
||||
ticker = NULL;
|
||||
framesRapid = 0;
|
||||
gotValidated = true;
|
||||
@@ -166,8 +167,13 @@ void SerialWorker::sendFrame(const CANFrame *frame)
|
||||
|
||||
//qDebug() << "Sending out frame with id " << frame->ID;
|
||||
|
||||
//show our sent frames in the list too. This happens even if we're not connected.
|
||||
model->addFrame(tempFrame, false);
|
||||
//show our sent frames in the list too. This happens even if we're not connected.
|
||||
/* model lives in UI thread, we need to call invokeMethod */
|
||||
QMetaObject::invokeMethod(model, "addFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(CANFrame, tempFrame),
|
||||
Q_ARG(bool, false));
|
||||
|
||||
framesRapid++;
|
||||
|
||||
if (serial == NULL) return;
|
||||
@@ -275,56 +281,61 @@ void SerialWorker::procRXChar(unsigned char c)
|
||||
switch (rx_step)
|
||||
{
|
||||
case 0:
|
||||
buildFrame->timestamp = c;
|
||||
buildFrame.timestamp = c;
|
||||
break;
|
||||
case 1:
|
||||
buildFrame->timestamp |= (uint)(c << 8);
|
||||
buildFrame.timestamp |= (uint)(c << 8);
|
||||
break;
|
||||
case 2:
|
||||
buildFrame->timestamp |= (uint)c << 16;
|
||||
buildFrame.timestamp |= (uint)c << 16;
|
||||
break;
|
||||
case 3:
|
||||
buildFrame->timestamp |= (uint)c << 24;
|
||||
buildFrame.timestamp |= (uint)c << 24;
|
||||
break;
|
||||
case 4:
|
||||
buildFrame->ID = c;
|
||||
buildFrame.ID = c;
|
||||
break;
|
||||
case 5:
|
||||
buildFrame->ID |= c << 8;
|
||||
buildFrame.ID |= c << 8;
|
||||
break;
|
||||
case 6:
|
||||
buildFrame->ID |= c << 16;
|
||||
buildFrame.ID |= c << 16;
|
||||
break;
|
||||
case 7:
|
||||
buildFrame->ID |= c << 24;
|
||||
if ((buildFrame->ID & 1 << 31) == 1 << 31)
|
||||
buildFrame.ID |= c << 24;
|
||||
if ((buildFrame.ID & 1 << 31) == 1 << 31)
|
||||
{
|
||||
buildFrame->ID &= 0x7FFFFFFF;
|
||||
buildFrame->extended = true;
|
||||
buildFrame.ID &= 0x7FFFFFFF;
|
||||
buildFrame.extended = true;
|
||||
}
|
||||
else buildFrame->extended = false;
|
||||
else buildFrame.extended = false;
|
||||
break;
|
||||
case 8:
|
||||
buildFrame->len = c & 0xF;
|
||||
if (buildFrame->len > 8) buildFrame->len = 8;
|
||||
buildFrame->bus = (c & 0xF0) >> 4;
|
||||
buildFrame.len = c & 0xF;
|
||||
if (buildFrame.len > 8) buildFrame.len = 8;
|
||||
buildFrame.bus = (c & 0xF0) >> 4;
|
||||
break;
|
||||
default:
|
||||
if (rx_step < buildFrame->len + 9)
|
||||
if (rx_step < buildFrame.len + 9)
|
||||
{
|
||||
buildFrame->data[rx_step - 9] = c;
|
||||
buildFrame.data[rx_step - 9] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
rx_state = IDLE;
|
||||
rx_step = 0;
|
||||
//qDebug() << "emit from serial handler to main form id: " << buildFrame->ID;
|
||||
//qDebug() << "emit from serial handler to main form id: " << buildFrame.ID;
|
||||
//if (capturing)
|
||||
//{
|
||||
buildFrame->isReceived = true;
|
||||
model->addFrame(*buildFrame, false);
|
||||
buildFrame.isReceived = true;
|
||||
/* model lives in UI thread, we need to call invokeMethod */
|
||||
QMetaObject::invokeMethod(model, "addFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(CANFrame, buildFrame),
|
||||
Q_ARG(bool, false));
|
||||
|
||||
//take the time the frame came in and try to resync the time base.
|
||||
if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame->timestamp / 1000);
|
||||
if (continuousTimeSync) txTimestampBasis = QDateTime::currentMSecsSinceEpoch() - (buildFrame.timestamp / 1000);
|
||||
framesRapid++;
|
||||
//}
|
||||
}
|
||||
@@ -566,6 +577,64 @@ void SerialWorker::updatePortName(QString portName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SerialWorker::updateBusSettings(CANBus bus)
|
||||
{
|
||||
int busNum = bus.busNum - busBase;
|
||||
if (busNum < 0) return;
|
||||
if (busNum >= numBuses) return;
|
||||
qDebug() << "About to update bus " << busNum << " on GVRET";
|
||||
if (busNum == 0)
|
||||
{
|
||||
can0Baud = bus.getSpeed();
|
||||
can0Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can0Baud |= 0x40000000;
|
||||
can0Enabled = true;
|
||||
}
|
||||
else can0Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can0Baud |= 0x20000000;
|
||||
can0ListenOnly = true;
|
||||
}
|
||||
else can0ListenOnly = false;
|
||||
}
|
||||
if (busNum == 1)
|
||||
{
|
||||
can1Baud = bus.getSpeed();
|
||||
can1Baud |= 0x80000000;
|
||||
if (bus.isActive())
|
||||
{
|
||||
can1Baud |= 0x40000000;
|
||||
can1Enabled = true;
|
||||
}
|
||||
else can1Enabled = false;
|
||||
|
||||
if (bus.isListenOnly())
|
||||
{
|
||||
can1Baud |= 0x20000000;
|
||||
can1ListenOnly = true;
|
||||
}
|
||||
else can1ListenOnly = false;
|
||||
|
||||
if (bus.isSingleWire())
|
||||
{
|
||||
can1Baud |= 0x10000000;
|
||||
deviceSingleWireMode = 1;
|
||||
}
|
||||
else deviceSingleWireMode = 0;
|
||||
}
|
||||
|
||||
updateBaudRates(can0Baud,can1Baud);
|
||||
}
|
||||
|
||||
|
||||
/************************************/
|
||||
|
||||
int SerialWorker::getNumBuses()
|
||||
{
|
||||
return 2;
|
||||
@@ -576,55 +645,4 @@ QString SerialWorker::getConnTypeName()
|
||||
return QString("GVRET");
|
||||
}
|
||||
|
||||
void SerialWorker::updateBusSettings(CAN_Bus *bus)
|
||||
{
|
||||
int busNum = bus->busNum - busBase;
|
||||
if (busNum < 0) return;
|
||||
if (busNum >= numBuses) return;
|
||||
qDebug() << "About to update bus " << busNum << " on GVRET";
|
||||
if (busNum == 0)
|
||||
{
|
||||
can0Baud = bus->getSpeed();
|
||||
can0Baud |= 0x80000000;
|
||||
if (bus->isActive())
|
||||
{
|
||||
can0Baud |= 0x40000000;
|
||||
can0Enabled = true;
|
||||
}
|
||||
else can0Enabled = false;
|
||||
|
||||
if (bus->isListenOnly())
|
||||
{
|
||||
can0Baud |= 0x20000000;
|
||||
can0ListenOnly = true;
|
||||
}
|
||||
else can0ListenOnly = false;
|
||||
}
|
||||
if (busNum == 1)
|
||||
{
|
||||
can1Baud = bus->getSpeed();
|
||||
can1Baud |= 0x80000000;
|
||||
if (bus->isActive())
|
||||
{
|
||||
can1Baud |= 0x40000000;
|
||||
can1Enabled = true;
|
||||
}
|
||||
else can1Enabled = false;
|
||||
|
||||
if (bus->isListenOnly())
|
||||
{
|
||||
can1Baud |= 0x20000000;
|
||||
can1ListenOnly = true;
|
||||
}
|
||||
else can1ListenOnly = false;
|
||||
|
||||
if (bus->isSingleWire())
|
||||
{
|
||||
can1Baud |= 0x10000000;
|
||||
deviceSingleWireMode = 1;
|
||||
}
|
||||
else deviceSingleWireMode = 0;
|
||||
}
|
||||
|
||||
updateBaudRates(can0Baud,can1Baud);
|
||||
}
|
||||
#endif
|
||||
|
||||
+6
-4
@@ -8,7 +8,8 @@
|
||||
#include <QTimer>
|
||||
#include "can_structs.h"
|
||||
#include "canframemodel.h"
|
||||
#include "canconnection.h"
|
||||
//#include "canconnection_old.h"
|
||||
|
||||
|
||||
namespace SERIALSTATE {
|
||||
|
||||
@@ -29,6 +30,7 @@ enum STATE //keep this enum synchronized with the Arduino firmware project
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
using namespace SERIALSTATE;
|
||||
class SerialWorker : public CANConnection
|
||||
{
|
||||
@@ -57,7 +59,7 @@ public slots:
|
||||
//void stopFrameCapture(int) override;
|
||||
//void startFrameCapture(int) override;
|
||||
void updatePortName(QString) override; //string version of the port to connect to. This base doesnt know a thing about this value
|
||||
void updateBusSettings(CAN_Bus *bus) override;
|
||||
void updateBusSettings(CANBus) override;
|
||||
|
||||
private:
|
||||
bool doValidation;
|
||||
@@ -71,7 +73,7 @@ private:
|
||||
int framesRapid;
|
||||
STATE rx_state;
|
||||
int rx_step;
|
||||
CANFrame *buildFrame;
|
||||
CANFrame buildFrame;
|
||||
int can0Baud, can1Baud;
|
||||
bool can0Enabled, can1Enabled;
|
||||
bool can0ListenOnly, can1ListenOnly;
|
||||
@@ -83,5 +85,5 @@ private:
|
||||
void procRXChar(unsigned char);
|
||||
void sendCommValidation();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // SERIALTHREAD_H
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
QT += widgets testlib
|
||||
QT -= gui
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
INCLUDEPATH += ../utils
|
||||
|
||||
SOURCES += \
|
||||
tst_lfqueue.cpp
|
||||
|
||||
|
||||
#HEADERS += \
|
||||
# ../utils/lfqueue.h
|
||||
|
||||
target.path= .
|
||||
INSTALLS += target
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtConcurrent/qtconcurrentrun.h>
|
||||
|
||||
#include "lfqueue.h"
|
||||
|
||||
class TestLFQueue: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
private slots:
|
||||
void setSize_data();
|
||||
void setSize();
|
||||
void exchange_data();
|
||||
void exchange();
|
||||
};
|
||||
|
||||
|
||||
void TestLFQueue::setSize_data()
|
||||
{
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<bool>("result");
|
||||
|
||||
QTest::newRow("-1") << -1 << false;
|
||||
QTest::newRow("0") << 0 << true;
|
||||
QTest::newRow("10") << 10 << true;
|
||||
QTest::newRow("2000") << 20000 << true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::setSize()
|
||||
{
|
||||
QFETCH(int, size);
|
||||
QFETCH(bool, result);
|
||||
|
||||
LFQueue<void*> queue;
|
||||
QCOMPARE(queue.setSize(size), result);
|
||||
}
|
||||
|
||||
|
||||
void readerThread(LFQueue<int>* pQueue_p, int pSize, bool pSleep) {
|
||||
int* val_p;
|
||||
|
||||
for(int i=0; i<pSize ; i++) {
|
||||
while(! (val_p = pQueue_p->peek()) );
|
||||
QVERIFY(val_p);
|
||||
|
||||
QCOMPARE(*val_p, i);
|
||||
pQueue_p->dequeue();
|
||||
|
||||
if(pSleep)
|
||||
QThread::msleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::exchange_data()
|
||||
{
|
||||
QTest::addColumn<int>("size");
|
||||
QTest::addColumn<bool>("writerSleep");
|
||||
QTest::addColumn<bool>("readerSleep");
|
||||
|
||||
QTest::newRow("nosleep") << 1000 << false << false;
|
||||
QTest::newRow("readersleep") << 1000 << false << true;
|
||||
QTest::newRow("writersleep") << 1000 << true << false;
|
||||
}
|
||||
|
||||
|
||||
void TestLFQueue::exchange()
|
||||
{
|
||||
LFQueue<int> queue;
|
||||
QFETCH(int, size);
|
||||
QFETCH(bool, writerSleep);
|
||||
QFETCH(bool, readerSleep);
|
||||
|
||||
int* val_p;
|
||||
QCOMPARE(queue.setSize(2), true);
|
||||
|
||||
QFuture<void> thread = QtConcurrent::run(readerThread, &queue, size, readerSleep);
|
||||
|
||||
for(int i=0; i<size ; i++) {
|
||||
while(! (val_p = queue.get()) );
|
||||
QVERIFY(val_p);
|
||||
|
||||
*val_p = i;
|
||||
queue.queue();
|
||||
|
||||
if(writerSleep)
|
||||
QThread::msleep(1);
|
||||
}
|
||||
|
||||
thread.waitForFinished();
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN(TestLFQueue)
|
||||
#include "tst_lfqueue.moc"
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef LFQUEUE_H
|
||||
#define LFQUEUE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
/* macros */
|
||||
#define IS_EMPTY() ( mWIdx.load() == mRIdx.load() )
|
||||
#define IS_FULL() ( (mWIdx.load()+1)%mSize == mRIdx.load() )
|
||||
|
||||
|
||||
template<class T>
|
||||
class LFQueue
|
||||
{
|
||||
public:
|
||||
LFQueue() : mSize(0), mArray(NULL){}
|
||||
|
||||
~LFQueue() {setSize(0);}
|
||||
|
||||
bool setSize(int size) {
|
||||
if(size<0)
|
||||
return false;
|
||||
|
||||
if(mArray) {
|
||||
delete[] mArray;
|
||||
mArray = NULL;
|
||||
}
|
||||
|
||||
if(size>0) {
|
||||
mArray = new T[size];
|
||||
if(mArray)
|
||||
mSize = size;
|
||||
return ( mArray!=NULL );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void flush() {
|
||||
mRIdx.store(0);
|
||||
mWIdx.store(0);
|
||||
}
|
||||
|
||||
T* get() {
|
||||
if(IS_FULL())
|
||||
return NULL;
|
||||
|
||||
return &(mArray[mWIdx.loadAcquire()]); /* prevent memory reordering (belt and braces) */
|
||||
}
|
||||
|
||||
|
||||
void queue() {
|
||||
#ifdef QT_DEBUG
|
||||
if(IS_FULL())
|
||||
qCritical() << "BUG: queueing in full queue";
|
||||
#endif
|
||||
|
||||
int wIdx = mWIdx.load();
|
||||
mWIdx.storeRelease((wIdx+1)%mSize);
|
||||
}
|
||||
|
||||
|
||||
T* peek() {
|
||||
if(IS_EMPTY())
|
||||
return NULL;
|
||||
|
||||
return &(mArray[mRIdx.loadAcquire()]); /* prevent memory reordering (belt and braces) */
|
||||
}
|
||||
|
||||
|
||||
void dequeue() {
|
||||
#ifdef QT_DEBUG
|
||||
if(IS_EMPTY())
|
||||
qCritical() << "BUG: dequeueing an empty queue";
|
||||
#endif
|
||||
|
||||
int rIdx = mRIdx.load();
|
||||
mRIdx.storeRelease((rIdx+1)%mSize);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
int mSize;
|
||||
T* mArray;
|
||||
|
||||
QAtomicInt mRIdx;
|
||||
QAtomicInt mWIdx;
|
||||
};
|
||||
|
||||
#endif // LFQUEUE_H
|
||||
Reference in New Issue
Block a user