+13
-5
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
#-------------------------------------------------
|
#-------------------------------------------------
|
||||||
|
|
||||||
QT += core gui
|
QT += core gui serialbus
|
||||||
|
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport qml
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets serialport printsupport qml
|
||||||
|
|
||||||
@@ -50,8 +50,11 @@ SOURCES += main.cpp\
|
|||||||
isotp_interpreterwindow.cpp \
|
isotp_interpreterwindow.cpp \
|
||||||
isotp_handler.cpp \
|
isotp_handler.cpp \
|
||||||
canconnectionmodel.cpp \
|
canconnectionmodel.cpp \
|
||||||
canconnection.cpp \
|
canbus.cpp \
|
||||||
canconnectioncontainer.cpp
|
connections/canconnection.cpp \
|
||||||
|
connections/socketcan.cpp \
|
||||||
|
connections/canconfactory.cpp \
|
||||||
|
connections/gvretserial.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
can_structs.h \
|
can_structs.h \
|
||||||
@@ -88,8 +91,13 @@ HEADERS += mainwindow.h \
|
|||||||
isotp_interpreterwindow.h \
|
isotp_interpreterwindow.h \
|
||||||
isotp_handler.h \
|
isotp_handler.h \
|
||||||
canconnectionmodel.h \
|
canconnectionmodel.h \
|
||||||
canconnection.h \
|
canbus.h \
|
||||||
canconnectioncontainer.h
|
utils/lfqueue.h \
|
||||||
|
connections/canconnection.h \
|
||||||
|
connections/socketcan.h \
|
||||||
|
connections/canconconst.h \
|
||||||
|
connections/canconfactory.h \
|
||||||
|
connections/gvretserial.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
graphingwindow.ui \
|
graphingwindow.ui \
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
class CANFrame
|
struct CANFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int ID;
|
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
|
|
||||||
+75
-54
@@ -1,5 +1,4 @@
|
|||||||
#include "canconnection.h"
|
#include "connections/canconnection.h"
|
||||||
#include "canconnectioncontainer.h"
|
|
||||||
#include "canconnectionmodel.h"
|
#include "canconnectionmodel.h"
|
||||||
|
|
||||||
CANConnectionModel::CANConnectionModel(QObject *parent)
|
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
|
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"));
|
return QString(tr("Single Wire"));
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
|
return QString(tr("Status"));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
return QString(tr("Active"));
|
return QString(tr("Active"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -52,100 +49,124 @@ QVariant CANConnectionModel::headerData(int section, Qt::Orientation orientation
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CANConnectionModel::rowCount(const QModelIndex &parent) const
|
|
||||||
{
|
|
||||||
return buses.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
int CANConnectionModel::columnCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return 7;
|
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
|
QVariant CANConnectionModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
if (!index.isValid())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
if (index.row() >= (buses.count()))
|
|
||||||
return QVariant();
|
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
CAN_Bus bus = buses[index.row()];
|
int busId;
|
||||||
CANConnection *conn = bus.connection;
|
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())
|
switch (index.column())
|
||||||
{
|
{
|
||||||
case 0: //bus
|
case 0: //bus
|
||||||
return QString::number(bus.busNum);
|
return QString::number(busId);
|
||||||
break;
|
break;
|
||||||
case 1: //type
|
case 1: //type
|
||||||
if (conn) return conn->getConnTypeName();
|
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";
|
else qDebug() << "Tried to show connection type but connection was NULL";
|
||||||
break;
|
break;
|
||||||
case 2: //port
|
case 2: //port
|
||||||
if (conn) return conn->getConnPortName();
|
if (conn_p) return conn_p->getPort();
|
||||||
else qDebug() << "Tried to show connection port but connection was NULL";
|
else qDebug() << "Tried to show connection port but connection was NULL";
|
||||||
break;
|
break;
|
||||||
case 3: //speed
|
case 3: //speed
|
||||||
return QString::number(bus.speed);
|
return QString::number(bus.speed);
|
||||||
break;
|
|
||||||
case 4: //Listen Only
|
case 4: //Listen Only
|
||||||
if (bus.listenOnly) return QString("True");
|
return (bus.listenOnly) ? "True" : "False";
|
||||||
else return QString("False");
|
|
||||||
break;
|
|
||||||
case 5: //Single Wire
|
case 5: //Single Wire
|
||||||
if (bus.singleWire) return QString("True");
|
return (bus.singleWire) ? "True" : "False";
|
||||||
else return QString("False");
|
case 6: //Status
|
||||||
break;
|
return (conn_p->getStatus()==CANCon::CONNECTED) ? "Connected" : "Not Connected";
|
||||||
case 6: //Active
|
case 7: //Active
|
||||||
if (bus.active) return QString("True");
|
return (bus.active) ? "True" : "False";
|
||||||
else return QString("False");
|
default: {}
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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();
|
beginResetModel();
|
||||||
buses.append(bus);
|
mConns.append(pConn_p);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
CAN_Bus* CANConnectionModel::getBus(int bus)
|
|
||||||
|
void CANConnectionModel::remove(CANConnection* pConn_p)
|
||||||
{
|
{
|
||||||
if (bus < 0) return NULL;
|
beginResetModel();
|
||||||
if (bus >= buses.count()) return NULL;
|
mConns.removeOne(pConn_p);
|
||||||
return &buses[bus];
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
CANConnection* CANConnectionModel::getConnection(int conn)
|
|
||||||
|
QList<CANConnection*>& CANConnectionModel::getConnections()
|
||||||
{
|
{
|
||||||
if (conn < 0) return NULL;
|
return mConns;
|
||||||
if (conn >= connections.count()) return NULL;
|
|
||||||
return connections[conn]->getRef();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CAN_Bus* CANConnectionModel::findBusByNum(int bus)
|
|
||||||
|
CANConnection* CANConnectionModel::getAtIdx(int pIdx, int& pBusId) const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < buses.count(); i++)
|
if (pIdx < 0)
|
||||||
{
|
return NULL;
|
||||||
if (buses[i].busNum == bus)
|
|
||||||
{
|
int i=0;
|
||||||
return &buses[i];
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CANConnectionModel::refreshView()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|||||||
+12
-12
@@ -1,12 +1,13 @@
|
|||||||
#ifndef CANCONNECTIONMODEL_H
|
#ifndef CANCONNECTIONMODEL_H
|
||||||
#define CANCONNECTIONMODEL_H
|
#define CANCONNECTIONMODEL_H
|
||||||
|
|
||||||
#include "canconnection.h"
|
|
||||||
#include "canconnectioncontainer.h"
|
|
||||||
|
|
||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
class CANConnectionContainer;
|
#include "canbus.h"
|
||||||
|
#include "connections/canconnection.h"
|
||||||
|
#include "connectionwindow.h"
|
||||||
|
|
||||||
|
|
||||||
class CANConnectionModel : public QAbstractTableModel
|
class CANConnectionModel : public QAbstractTableModel
|
||||||
{
|
{
|
||||||
@@ -18,22 +19,21 @@ public:
|
|||||||
// Header:
|
// Header:
|
||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
void addConnection(CANConnection *conn);
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
void addBus(CAN_Bus &bus);
|
|
||||||
CAN_Bus* getBus(int bus);
|
void add(CANConnection* pConn_p);
|
||||||
CANConnection* getConnection(int conn);
|
void remove(CANConnection* pConn_p);
|
||||||
|
|
||||||
|
QList<CANConnection*>& getConnections();
|
||||||
|
CANConnection* getAtIdx(int, int&) const;
|
||||||
void refreshView();
|
void refreshView();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<CANConnectionContainer *> connections;
|
QList<CANConnection*> mConns;
|
||||||
QList<CAN_Bus> buses;
|
|
||||||
|
|
||||||
CAN_Bus *findBusByNum(int bus);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CANCONNECTIONMODEL_H
|
#endif // CANCONNECTIONMODEL_H
|
||||||
|
|||||||
+3
-1
@@ -281,8 +281,10 @@ QVariant CANFrameModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CANFrameModel::addFrame(const CANFrame &frame, bool autoRefresh = false)
|
|
||||||
|
void CANFrameModel::addFrame(CANFrame& frame, bool autoRefresh = false)
|
||||||
{
|
{
|
||||||
|
/*TODO: remove mutex */
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
CANFrame tempFrame;
|
CANFrame tempFrame;
|
||||||
tempFrame = frame;
|
tempFrame = frame;
|
||||||
|
|||||||
+3
-1
@@ -23,7 +23,6 @@ public:
|
|||||||
int columnCount(const QModelIndex &) const;
|
int columnCount(const QModelIndex &) const;
|
||||||
int totalFrameCount();
|
int totalFrameCount();
|
||||||
|
|
||||||
void addFrame(const CANFrame &, bool);
|
|
||||||
void sendRefresh();
|
void sendRefresh();
|
||||||
void sendRefresh(int);
|
void sendRefresh(int);
|
||||||
void sendBulkRefresh(int);
|
void sendBulkRefresh(int);
|
||||||
@@ -46,6 +45,9 @@ public:
|
|||||||
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
|
const QVector<CANFrame> *getFilteredListReference() const; //Thus saith the Lord, NO.
|
||||||
const QMap<int, bool> *getFiltersReference() const; //this neither
|
const QMap<int, bool> *getFiltersReference() const; //this neither
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void addFrame(CANFrame&, bool);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updatedFiltersList();
|
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
|
||||||
+238
-114
@@ -1,6 +1,9 @@
|
|||||||
|
#include <QCanBus>
|
||||||
|
|
||||||
#include "connectionwindow.h"
|
#include "connectionwindow.h"
|
||||||
#include "ui_connectionwindow.h"
|
#include "ui_connectionwindow.h"
|
||||||
#include <QtNetwork/QNetworkInterface>
|
#include "connections/canconfactory.h"
|
||||||
|
|
||||||
|
|
||||||
ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
||||||
QDialog(parent),
|
QDialog(parent),
|
||||||
@@ -10,7 +13,7 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
|||||||
|
|
||||||
settings = new QSettings();
|
settings = new QSettings();
|
||||||
|
|
||||||
qRegisterMetaType<CAN_Bus *>("CAN_Bus *");
|
qRegisterMetaType<CANBus>("CANBus");
|
||||||
qRegisterMetaType<const CANFrame *>("const CANFrame *");
|
qRegisterMetaType<const CANFrame *>("const CANFrame *");
|
||||||
qRegisterMetaType<const QList<CANFrame> *>("const QList<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(0, 50);
|
||||||
ui->tableConnections->setColumnWidth(1, 110);
|
ui->tableConnections->setColumnWidth(1, 110);
|
||||||
ui->tableConnections->setColumnWidth(2, 110);
|
ui->tableConnections->setColumnWidth(2, 110);
|
||||||
ui->tableConnections->setColumnWidth(3, 150);
|
ui->tableConnections->setColumnWidth(3, 110);
|
||||||
ui->tableConnections->setColumnWidth(4, 75);
|
ui->tableConnections->setColumnWidth(4, 75);
|
||||||
ui->tableConnections->setColumnWidth(5, 75);
|
ui->tableConnections->setColumnWidth(5, 75);
|
||||||
ui->tableConnections->setColumnWidth(6, 75);
|
ui->tableConnections->setColumnWidth(6, 75);
|
||||||
|
ui->tableConnections->setColumnWidth(7, 75);
|
||||||
|
|
||||||
int temp = settings->value("Main/DefaultConnectionType", 0).toInt();
|
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->ckSingleWire->setChecked(settings->value("Main/SingleWireMode", false).toBool());
|
||||||
|
|
||||||
ui->cbSpeed->addItem(tr("<Default>"));
|
ui->cbSpeed->addItem(tr("<Default>"));
|
||||||
ui->cbSpeed->addItem(tr("Disabled"));
|
|
||||||
ui->cbSpeed->addItem(tr("125000"));
|
ui->cbSpeed->addItem(tr("125000"));
|
||||||
ui->cbSpeed->addItem(tr("250000"));
|
ui->cbSpeed->addItem(tr("250000"));
|
||||||
ui->cbSpeed->addItem(tr("500000"));
|
ui->cbSpeed->addItem(tr("500000"));
|
||||||
@@ -44,7 +47,7 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
|||||||
ui->cbSpeed->addItem(tr("33333"));
|
ui->cbSpeed->addItem(tr("33333"));
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
ui->rbSocketCAN->setEnabled(true);
|
ui->rbSocketCAN->setEnabled(isSocketCanAvailable());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -57,14 +60,38 @@ ConnectionWindow::ConnectionWindow(CANFrameModel *cModel, QWidget *parent) :
|
|||||||
connect(ui->rbSocketCAN, &QAbstractButton::toggled, this, &ConnectionWindow::handleConnTypeChanged);
|
connect(ui->rbSocketCAN, &QAbstractButton::toggled, this, &ConnectionWindow::handleConnTypeChanged);
|
||||||
connect(ui->btnRevert, &QPushButton::clicked, this, &ConnectionWindow::handleRevert);
|
connect(ui->btnRevert, &QPushButton::clicked, this, &ConnectionWindow::handleRevert);
|
||||||
connect(ui->tableConnections->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ConnectionWindow::handleConnSelectionChanged);
|
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->btnNewConn, &QPushButton::clicked, this, &ConnectionWindow::handleNewConn);
|
||||||
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
connect(ui->btnActivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleEnableAll);
|
||||||
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
connect(ui->btnDeactivateAll, &QPushButton::clicked, this, &ConnectionWindow::handleDisableAll);
|
||||||
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
connect(ui->btnRemoveBus, &QPushButton::clicked, this, &ConnectionWindow::handleRemoveConn);
|
||||||
|
|
||||||
|
|
||||||
|
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()
|
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 settings;
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
@@ -76,6 +103,20 @@ void ConnectionWindow::showEvent(QShowEvent* event)
|
|||||||
handleConnTypeChanged();
|
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()
|
void ConnectionWindow::handleNewConn()
|
||||||
{
|
{
|
||||||
ui->tableConnections->selectionModel()->clearSelection();
|
ui->tableConnections->selectionModel()->clearSelection();
|
||||||
@@ -83,100 +124,113 @@ void ConnectionWindow::handleNewConn()
|
|||||||
handleConnSelectionChanged();
|
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()
|
void ConnectionWindow::handleEnableAll()
|
||||||
{
|
{
|
||||||
|
setActiveAll(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::handleDisableAll()
|
void ConnectionWindow::handleDisableAll()
|
||||||
{
|
{
|
||||||
|
setActiveAll(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::handleConnTypeChanged()
|
void ConnectionWindow::handleConnTypeChanged()
|
||||||
{
|
{
|
||||||
if (ui->rbGVRET->isChecked()) getSerialPorts();
|
if (ui->rbGVRET->isChecked()) selectSerial();
|
||||||
if (ui->rbKvaser->isChecked()) getKvaserPorts();
|
if (ui->rbKvaser->isChecked()) selectKvaser();
|
||||||
if (ui->rbSocketCAN->isChecked()) getSocketcanPorts();
|
if (ui->rbSocketCAN->isChecked()) selectSocketCan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::connectionSuccess(CANConnection *conn)
|
|
||||||
{
|
|
||||||
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
|
/* status */
|
||||||
else if (ui->cbSpeed->currentIndex() == 1)
|
void ConnectionWindow::connectionStatus(CANCon::status pStatus)
|
||||||
{
|
{
|
||||||
bus.speed = 0;
|
qDebug() << "Connectionstatus changed";
|
||||||
bus.active = false;
|
connModel->refreshView();
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionWindow::handleOKButton()
|
void ConnectionWindow::handleOKButton()
|
||||||
{
|
{
|
||||||
QString conn;
|
|
||||||
int connType = 0;
|
|
||||||
int whichRow = ui->tableConnections->selectionModel()->currentIndex().row();
|
int whichRow = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||||
qDebug() << "OK pressed. Row " << whichRow;
|
|
||||||
|
CANConnection* conn_p = NULL;
|
||||||
|
|
||||||
if (whichRow > -1)
|
if (whichRow > -1)
|
||||||
{
|
{
|
||||||
//load settings from GUI into appropriate CAN_Bus entry and then send it off to the appropriate
|
int busId;
|
||||||
//CANConnection object
|
CANBus bus;
|
||||||
CAN_Bus *bus = connModel->getBus(whichRow);
|
bool ret;
|
||||||
bus->setListenOnly(ui->ckListenOnly->isChecked());
|
|
||||||
bus->setSingleWire(ui->ckSingleWire->isChecked());
|
conn_p = connModel->getAtIdx(whichRow, busId);
|
||||||
bus->setEnabled(ui->ckEnabled->isChecked());
|
if(!conn_p) return;
|
||||||
if (ui->cbSpeed->currentIndex() == 1)
|
|
||||||
|
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.speed = 0;
|
||||||
bus->setEnabled(false);
|
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
|
/* update bus settings */
|
||||||
QMetaObject::invokeMethod(bus->connection, "updateBusSettings",
|
conn_p->setBusSettings(busId, bus);
|
||||||
Qt::QueuedConnection,
|
|
||||||
Q_ARG(CAN_Bus *, bus));
|
|
||||||
connModel->refreshView();
|
connModel->refreshView();
|
||||||
}
|
}
|
||||||
else //new connection
|
else //new connection
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (ui->rbGVRET->isChecked())
|
if (ui->rbGVRET->isChecked())
|
||||||
{
|
{
|
||||||
|
|
||||||
SerialWorker *serial = new SerialWorker(canModel, connModel->rowCount());
|
SerialWorker *serial = new SerialWorker(canModel, connModel->rowCount());
|
||||||
connect(serial, SIGNAL(busStatus(int,int,int)), this, SLOT(receiveBusStatus(int,int,int)));
|
connect(serial, SIGNAL(busStatus(int,int,int)), this, SLOT(receiveBusStatus(int,int,int)));
|
||||||
connect(serial, SIGNAL(connectionSuccess(CANConnection*)), this, SLOT(connectionSuccess(CANConnection*)));
|
connect(serial, SIGNAL(connectionSuccess(CANConnection*)), this, SLOT(connectionSuccess(CANConnection*)));
|
||||||
connModel->addConnection(serial);
|
CANConnectionContainer* container = new CANConnectionContainer(serial);
|
||||||
|
|
||||||
|
|
||||||
qDebug() << "Setup initial connection object";
|
qDebug() << "Setup initial connection object";
|
||||||
|
|
||||||
CAN_Bus bus;
|
CANBus bus;
|
||||||
bus.active = ui->ckEnabled->isChecked();
|
bus.active = ui->ckEnabled->isChecked();
|
||||||
bus.busNum = serial->getBusBase();
|
bus.busNum = serial->getBusBase();
|
||||||
bus.connection = serial;
|
bus.container = container;
|
||||||
bus.listenOnly = ui->ckListenOnly->isChecked();
|
bus.listenOnly = ui->ckListenOnly->isChecked();
|
||||||
bus.singleWire = ui->ckSingleWire->isChecked();
|
bus.singleWire = ui->ckSingleWire->isChecked();
|
||||||
|
|
||||||
@@ -187,6 +241,7 @@ void ConnectionWindow::handleOKButton()
|
|||||||
bus.active = false;
|
bus.active = false;
|
||||||
}
|
}
|
||||||
else bus.speed = ui->cbSpeed->currentText().toInt();
|
else bus.speed = ui->cbSpeed->currentText().toInt();
|
||||||
|
|
||||||
connModel->addBus(bus);
|
connModel->addBus(bus);
|
||||||
|
|
||||||
int numBuses = serial->getNumBuses();
|
int numBuses = serial->getNumBuses();
|
||||||
@@ -197,7 +252,7 @@ void ConnectionWindow::handleOKButton()
|
|||||||
bus.singleWire = false;
|
bus.singleWire = false;
|
||||||
bus.speed = 250000;
|
bus.speed = 250000;
|
||||||
bus.busNum = serial->getBusBase() + i;
|
bus.busNum = serial->getBusBase() + i;
|
||||||
bus.connection = serial;
|
bus.container = container;
|
||||||
connModel->addBus(bus);
|
connModel->addBus(bus);
|
||||||
qDebug() << "Added bus " << bus.busNum;
|
qDebug() << "Added bus " << bus.busNum;
|
||||||
}
|
}
|
||||||
@@ -206,22 +261,45 @@ void ConnectionWindow::handleOKButton()
|
|||||||
QMetaObject::invokeMethod(serial, "updatePortName",
|
QMetaObject::invokeMethod(serial, "updatePortName",
|
||||||
Qt::QueuedConnection,
|
Qt::QueuedConnection,
|
||||||
Q_ARG(QString, ui->cbPort->currentText()));
|
Q_ARG(QString, ui->cbPort->currentText()));
|
||||||
}
|
#endif
|
||||||
else if (ui->rbKvaser->isChecked())
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
/* create connection */
|
||||||
else if (ui->rbSocketCAN->isChecked())
|
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)
|
void ConnectionWindow::receiveBusStatus(int bus, int speed, int status)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
qDebug() << "bus " << bus << " speed " << speed << " status " << status;
|
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 & 40) busRef->setSpeed(speed);
|
||||||
if (status & 8) //update enabled status
|
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);
|
busRef->setListenOnly((status & 4)?true:false);
|
||||||
}
|
}
|
||||||
connModel->refreshView();
|
connModel->refreshView();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::handleConnSelectionChanged()
|
void ConnectionWindow::handleConnSelectionChanged()
|
||||||
{
|
{
|
||||||
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
int selIdx = ui->tableConnections->selectionModel()->currentIndex().row();
|
||||||
qDebug() << "Selection: " << selIdx;
|
|
||||||
if (selIdx == -1)
|
if (selIdx == -1)
|
||||||
{
|
{
|
||||||
ui->btnOK->setText(tr("Create New Connection"));
|
ui->btnOK->setText(tr("Create New Connection"));
|
||||||
|
|
||||||
ui->cbPort->setEnabled(true);
|
ui->cbPort->setEnabled(true);
|
||||||
ui->rbGVRET->setEnabled(true);
|
ui->rbGVRET->setEnabled(true);
|
||||||
ui->rbKvaser->setEnabled(true);
|
ui->rbKvaser->setEnabled(true);
|
||||||
ui->rbSocketCAN->setEnabled(true);
|
ui->rbSocketCAN->setEnabled(true);
|
||||||
|
ui->cbSpeed->setEnabled(false);
|
||||||
|
|
||||||
ui->cbPort->setCurrentIndex(0);
|
ui->cbPort->setCurrentIndex(0);
|
||||||
ui->ckListenOnly->setChecked(false);
|
ui->ckListenOnly->setChecked(false);
|
||||||
ui->ckSingleWire->setChecked(false);
|
ui->ckSingleWire->setChecked(false);
|
||||||
@@ -256,25 +337,43 @@ void ConnectionWindow::handleConnSelectionChanged()
|
|||||||
}
|
}
|
||||||
else
|
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->btnOK->setText(tr("Update Connection Settings"));
|
||||||
|
|
||||||
ui->cbPort->setEnabled(false);
|
ui->cbPort->setEnabled(false);
|
||||||
ui->rbGVRET->setEnabled(false);
|
ui->rbGVRET->setEnabled(false);
|
||||||
ui->rbKvaser->setEnabled(false);
|
ui->rbKvaser->setEnabled(false);
|
||||||
ui->rbSocketCAN->setEnabled(false);
|
ui->rbSocketCAN->setEnabled(false);
|
||||||
CAN_Bus *bus = connModel->getBus(selIdx);
|
ui->cbSpeed->setEnabled(true);
|
||||||
if (bus->connection->getConnTypeName() == "GVRET") ui->rbGVRET->setChecked(true);
|
|
||||||
if (bus->connection->getConnTypeName() == "KVASER") ui->rbKvaser->setChecked(true);
|
switch(conn_p->getType()) {
|
||||||
if (bus->connection->getConnTypeName() == "SOCKETCAN") ui->rbSocketCAN->setChecked(true);
|
case CANCon::GVRET_SERIAL: ui->rbGVRET->setChecked(true); break;
|
||||||
ui->ckListenOnly->setChecked(bus->isListenOnly());
|
case CANCon::KVASER: ui->rbKvaser->setChecked(true); break;
|
||||||
ui->ckSingleWire->setChecked(bus->isSingleWire());
|
case CANCon::SOCKETCAN: ui->rbSocketCAN->setChecked(true); break;
|
||||||
ui->ckEnabled->setChecked(bus->isActive());
|
default: {}
|
||||||
int speed = bus->getSpeed();
|
}
|
||||||
|
|
||||||
|
ui->ckListenOnly->setChecked(bus.isListenOnly());
|
||||||
|
ui->ckSingleWire->setChecked(bus.isSingleWire());
|
||||||
|
ui->ckEnabled->setChecked(bus.isActive());
|
||||||
|
int speed = bus.getSpeed();
|
||||||
setSpeed(speed);
|
setSpeed(speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::getSerialPorts()
|
|
||||||
|
void ConnectionWindow::selectSerial()
|
||||||
{
|
{
|
||||||
|
/* set combobox page visible */
|
||||||
|
ui->stPort->setCurrentWidget(ui->cbPage);
|
||||||
|
|
||||||
ui->cbPort->clear();
|
ui->cbPort->clear();
|
||||||
ports = QSerialPortInfo::availablePorts();
|
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
|
#ifdef Q_OS_LINUX
|
||||||
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
|
/* set edit text page visible */
|
||||||
QString interfaceName;
|
ui->stPort->setCurrentWidget(ui->etPage);
|
||||||
|
|
||||||
ui->cbPort->clear();
|
|
||||||
|
|
||||||
foreach (QNetworkInterface interface, interfaces)
|
|
||||||
{
|
|
||||||
interfaceName = interface.name().toLower();
|
|
||||||
qDebug() << "Interface: " << interface.name();
|
|
||||||
if (interfaceName.contains("can"))
|
|
||||||
{
|
|
||||||
ui->cbPort->addItem(interfaceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,16 +445,30 @@ int ConnectionWindow::getSpeed()
|
|||||||
|
|
||||||
QString ConnectionWindow::getPortName()
|
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";
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionType::ConnectionType ConnectionWindow::getConnectionType()
|
return "";
|
||||||
{
|
|
||||||
if (ui->rbGVRET->isChecked()) return ConnectionType::GVRET_SERIAL;
|
|
||||||
if (ui->rbKvaser->isChecked()) return ConnectionType::KVASER;
|
|
||||||
if (ui->rbSocketCAN->isChecked()) return ConnectionType::SOCKETCAN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CANCon::type ConnectionWindow::getConnectionType()
|
||||||
|
{
|
||||||
|
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)
|
void ConnectionWindow::setSWMode(bool mode)
|
||||||
{
|
{
|
||||||
ui->ckSingleWire->setChecked(mode);
|
ui->ckSingleWire->setChecked(mode);
|
||||||
@@ -378,7 +482,21 @@ bool ConnectionWindow::getSWMode()
|
|||||||
|
|
||||||
void ConnectionWindow::handleRemoveConn()
|
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()
|
void ConnectionWindow::handleRevert()
|
||||||
@@ -386,31 +504,37 @@ void ConnectionWindow::handleRevert()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::handleEnableAll()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionWindow::handleDisableAll()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConnectionWindow::sendFrame(const CANFrame *frame)
|
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;
|
if (bus == NULL) return;
|
||||||
QMetaObject::invokeMethod(bus->connection, "sendFrame",
|
QMetaObject::invokeMethod(bus->getContainer()->getRef(), "sendFrame",
|
||||||
Qt::QueuedConnection,
|
Qt::QueuedConnection,
|
||||||
Q_ARG(const CANFrame *, frame));
|
Q_ARG(const CANFrame *, frame));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionWindow::sendFrameBatch(const QList<CANFrame> *frames)
|
void ConnectionWindow::sendFrameBatch(const QList<CANFrame> *frames)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (frames->count() == 0) return;
|
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;
|
if (bus == NULL) return;
|
||||||
QMetaObject::invokeMethod(bus->connection, "sendFrameBatch",
|
QMetaObject::invokeMethod(bus->getContainer()->getRef(), "sendFrameBatch",
|
||||||
Qt::QueuedConnection,
|
Qt::QueuedConnection,
|
||||||
Q_ARG(const QList<CANFrame> *, frames));
|
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
|
#ifndef CONNECTIONWINDOW_H
|
||||||
#define CONNECTIONWINDOW_H
|
#define CONNECTIONWINDOW_H
|
||||||
|
|
||||||
#include "canconnectionmodel.h"
|
|
||||||
|
|
||||||
#include <QSerialPortInfo>
|
#include <QSerialPortInfo>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include "canconnection.h"
|
#include <QTimer>
|
||||||
#include "serialworker.h"
|
//#include "canconnection_old.h"
|
||||||
|
//#include "serialworker.h"
|
||||||
|
#include "canconnectionmodel.h"
|
||||||
|
#include "canframemodel.h"
|
||||||
|
|
||||||
|
|
||||||
class CANConnectionModel;
|
class CANConnectionModel;
|
||||||
|
|
||||||
@@ -16,15 +20,6 @@ namespace Ui {
|
|||||||
class ConnectionWindow;
|
class ConnectionWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ConnectionType
|
|
||||||
{
|
|
||||||
enum ConnectionType
|
|
||||||
{
|
|
||||||
GVRET_SERIAL,
|
|
||||||
KVASER,
|
|
||||||
SOCKETCAN
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class ConnectionWindow : public QDialog
|
class ConnectionWindow : public QDialog
|
||||||
{
|
{
|
||||||
@@ -36,11 +31,11 @@ public:
|
|||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
int getSpeed();
|
int getSpeed();
|
||||||
QString getPortName(); //name of port to connect to
|
QString getPortName(); //name of port to connect to
|
||||||
ConnectionType::ConnectionType getConnectionType();
|
CANCon::type getConnectionType();
|
||||||
bool getSWMode();
|
bool getSWMode();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void updateBusSettings(CAN_Bus *bus);
|
void updateBusSettings(CANBus *bus);
|
||||||
void updatePortName(QString port);
|
void updatePortName(QString port);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -48,6 +43,8 @@ public slots:
|
|||||||
void setSWMode(bool mode);
|
void setSWMode(bool mode);
|
||||||
void sendFrame(const CANFrame *);
|
void sendFrame(const CANFrame *);
|
||||||
void sendFrameBatch(const QList<CANFrame> *);
|
void sendFrameBatch(const QList<CANFrame> *);
|
||||||
|
void setSuspendAll(bool);
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleOKButton();
|
void handleOKButton();
|
||||||
@@ -58,10 +55,10 @@ private slots:
|
|||||||
void handleDisableAll();
|
void handleDisableAll();
|
||||||
void handleRevert();
|
void handleRevert();
|
||||||
void handleNewConn();
|
void handleNewConn();
|
||||||
void handleEnableAll();
|
|
||||||
void handleDisableAll();
|
|
||||||
void receiveBusStatus(int bus, int speed, int status);
|
void receiveBusStatus(int bus, int speed, int status);
|
||||||
void connectionSuccess(CANConnection *conn);
|
void connectionStatus(CANCon::status);
|
||||||
|
|
||||||
|
void refreshCanList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ConnectionWindow *ui;
|
Ui::ConnectionWindow *ui;
|
||||||
@@ -69,11 +66,14 @@ private:
|
|||||||
QSettings *settings;
|
QSettings *settings;
|
||||||
CANConnectionModel *connModel;
|
CANConnectionModel *connModel;
|
||||||
CANFrameModel *canModel;
|
CANFrameModel *canModel;
|
||||||
|
QTimer mTicker;
|
||||||
|
|
||||||
|
|
||||||
void getSerialPorts();
|
void selectSerial();
|
||||||
void getKvaserPorts();
|
void selectKvaser();
|
||||||
void getSocketcanPorts();
|
void selectSocketCan();
|
||||||
|
bool isSocketCanAvailable();
|
||||||
|
void setActiveAll(bool pActive);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONNECTIONWINDOW_H
|
#endif // CONNECTIONWINDOW_H
|
||||||
|
|||||||
+65
-3
@@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1009</width>
|
<width>956</width>
|
||||||
<height>433</height>
|
<height>527</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@@ -129,7 +129,69 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<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>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="ckSingleWire">
|
<widget class="QCheckBox" name="ckSingleWire">
|
||||||
|
|||||||
+5
-7
@@ -47,7 +47,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
|
|
||||||
this->setWindowTitle("Savvy CAN V" + QString::number(VERSION));
|
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);
|
ui->canFramesView->setModel(model);
|
||||||
|
|
||||||
readSettings();
|
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.
|
//Automatically create the connection window so it can be updated even if we never opened it.
|
||||||
connectionWindow = new ConnectionWindow(model);
|
connectionWindow = new ConnectionWindow(model);
|
||||||
connect(connectionWindow, SIGNAL(updateConnectionSettings(QString,QString,int,int)), this, SLOT(updateConnectionSettings(QString,QString,int,int)));
|
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()
|
MainWindow::~MainWindow()
|
||||||
@@ -712,15 +714,11 @@ void MainWindow::toggleCapture()
|
|||||||
{
|
{
|
||||||
allowCapture = !allowCapture;
|
allowCapture = !allowCapture;
|
||||||
if (allowCapture)
|
if (allowCapture)
|
||||||
{
|
|
||||||
ui->btnCaptureToggle->setText("Suspend Capturing");
|
ui->btnCaptureToggle->setText("Suspend Capturing");
|
||||||
emit startFrameCapturing();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
ui->btnCaptureToggle->setText("Restart Capturing");
|
ui->btnCaptureToggle->setText("Restart Capturing");
|
||||||
emit stopFrameCapturing();
|
|
||||||
}
|
emit suspendCapturing(!allowCapture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::connectionSucceeded(int baud0, int baud1)
|
void MainWindow::connectionSucceeded(int baud0, int baud1)
|
||||||
|
|||||||
+1
-2
@@ -92,8 +92,7 @@ public slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendCANFrame(const CANFrame *, int);
|
void sendCANFrame(const CANFrame *, int);
|
||||||
void stopFrameCapturing();
|
void suspendCapturing(bool);
|
||||||
void startFrameCapturing();
|
|
||||||
|
|
||||||
//-1 = frames cleared, -2 = a new file has been loaded (so all frames are different), otherwise # of new frames
|
//-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
|
void framesUpdated(int numFrames); //something has updated the frame list
|
||||||
|
|||||||
+93
-75
@@ -5,13 +5,14 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
|
#if 0
|
||||||
SerialWorker::SerialWorker(CANFrameModel *model, int base) : CANConnection(model, base)
|
SerialWorker::SerialWorker(CANFrameModel *model, int base) : CANConnection(model, base)
|
||||||
{
|
{
|
||||||
qDebug() << "Serial Worker constructor";
|
qDebug() << "Serial Worker constructor";
|
||||||
serial = NULL;
|
serial = NULL;
|
||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
rx_step = 0;
|
rx_step = 0;
|
||||||
buildFrame = new CANFrame;
|
buildFrame;
|
||||||
ticker = NULL;
|
ticker = NULL;
|
||||||
framesRapid = 0;
|
framesRapid = 0;
|
||||||
gotValidated = true;
|
gotValidated = true;
|
||||||
@@ -167,7 +168,12 @@ void SerialWorker::sendFrame(const CANFrame *frame)
|
|||||||
//qDebug() << "Sending out frame with id " << frame->ID;
|
//qDebug() << "Sending out frame with id " << frame->ID;
|
||||||
|
|
||||||
//show our sent frames in the list too. This happens even if we're not connected.
|
//show our sent frames in the list too. This happens even if we're not connected.
|
||||||
model->addFrame(tempFrame, false);
|
/* model lives in UI thread, we need to call invokeMethod */
|
||||||
|
QMetaObject::invokeMethod(model, "addFrame",
|
||||||
|
Qt::QueuedConnection,
|
||||||
|
Q_ARG(CANFrame, tempFrame),
|
||||||
|
Q_ARG(bool, false));
|
||||||
|
|
||||||
framesRapid++;
|
framesRapid++;
|
||||||
|
|
||||||
if (serial == NULL) return;
|
if (serial == NULL) return;
|
||||||
@@ -275,56 +281,61 @@ void SerialWorker::procRXChar(unsigned char c)
|
|||||||
switch (rx_step)
|
switch (rx_step)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
buildFrame->timestamp = c;
|
buildFrame.timestamp = c;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
buildFrame->timestamp |= (uint)(c << 8);
|
buildFrame.timestamp |= (uint)(c << 8);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
buildFrame->timestamp |= (uint)c << 16;
|
buildFrame.timestamp |= (uint)c << 16;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
buildFrame->timestamp |= (uint)c << 24;
|
buildFrame.timestamp |= (uint)c << 24;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
buildFrame->ID = c;
|
buildFrame.ID = c;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
buildFrame->ID |= c << 8;
|
buildFrame.ID |= c << 8;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
buildFrame->ID |= c << 16;
|
buildFrame.ID |= c << 16;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
buildFrame->ID |= c << 24;
|
buildFrame.ID |= c << 24;
|
||||||
if ((buildFrame->ID & 1 << 31) == 1 << 31)
|
if ((buildFrame.ID & 1 << 31) == 1 << 31)
|
||||||
{
|
{
|
||||||
buildFrame->ID &= 0x7FFFFFFF;
|
buildFrame.ID &= 0x7FFFFFFF;
|
||||||
buildFrame->extended = true;
|
buildFrame.extended = true;
|
||||||
}
|
}
|
||||||
else buildFrame->extended = false;
|
else buildFrame.extended = false;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
buildFrame->len = c & 0xF;
|
buildFrame.len = c & 0xF;
|
||||||
if (buildFrame->len > 8) buildFrame->len = 8;
|
if (buildFrame.len > 8) buildFrame.len = 8;
|
||||||
buildFrame->bus = (c & 0xF0) >> 4;
|
buildFrame.bus = (c & 0xF0) >> 4;
|
||||||
break;
|
break;
|
||||||
default:
|
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
|
else
|
||||||
{
|
{
|
||||||
rx_state = IDLE;
|
rx_state = IDLE;
|
||||||
rx_step = 0;
|
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)
|
//if (capturing)
|
||||||
//{
|
//{
|
||||||
buildFrame->isReceived = true;
|
buildFrame.isReceived = true;
|
||||||
model->addFrame(*buildFrame, false);
|
/* 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.
|
//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++;
|
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()
|
int SerialWorker::getNumBuses()
|
||||||
{
|
{
|
||||||
return 2;
|
return 2;
|
||||||
@@ -576,55 +645,4 @@ QString SerialWorker::getConnTypeName()
|
|||||||
return QString("GVRET");
|
return QString("GVRET");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SerialWorker::updateBusSettings(CAN_Bus *bus)
|
#endif
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|||||||
+6
-4
@@ -8,7 +8,8 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include "can_structs.h"
|
#include "can_structs.h"
|
||||||
#include "canframemodel.h"
|
#include "canframemodel.h"
|
||||||
#include "canconnection.h"
|
//#include "canconnection_old.h"
|
||||||
|
|
||||||
|
|
||||||
namespace SERIALSTATE {
|
namespace SERIALSTATE {
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ enum STATE //keep this enum synchronized with the Arduino firmware project
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
using namespace SERIALSTATE;
|
using namespace SERIALSTATE;
|
||||||
class SerialWorker : public CANConnection
|
class SerialWorker : public CANConnection
|
||||||
{
|
{
|
||||||
@@ -57,7 +59,7 @@ public slots:
|
|||||||
//void stopFrameCapture(int) override;
|
//void stopFrameCapture(int) override;
|
||||||
//void startFrameCapture(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 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:
|
private:
|
||||||
bool doValidation;
|
bool doValidation;
|
||||||
@@ -71,7 +73,7 @@ private:
|
|||||||
int framesRapid;
|
int framesRapid;
|
||||||
STATE rx_state;
|
STATE rx_state;
|
||||||
int rx_step;
|
int rx_step;
|
||||||
CANFrame *buildFrame;
|
CANFrame buildFrame;
|
||||||
int can0Baud, can1Baud;
|
int can0Baud, can1Baud;
|
||||||
bool can0Enabled, can1Enabled;
|
bool can0Enabled, can1Enabled;
|
||||||
bool can0ListenOnly, can1ListenOnly;
|
bool can0ListenOnly, can1ListenOnly;
|
||||||
@@ -83,5 +85,5 @@ private:
|
|||||||
void procRXChar(unsigned char);
|
void procRXChar(unsigned char);
|
||||||
void sendCommValidation();
|
void sendCommValidation();
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
#endif // SERIALTHREAD_H
|
#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